diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp index a074761fa..4fce3ed2b 100644 --- a/StandAlone/StandAlone.cpp +++ b/StandAlone/StandAlone.cpp @@ -1,5 +1,7 @@ // //Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//Copyright (C) 2013 LunarG, Inc. +// //All rights reserved. // //Redistribution and use in source and binary forms, with or without @@ -99,6 +101,12 @@ void GenerateResources(TBuiltInResource& resources) resources.maxTextureImageUnits = 32; resources.maxFragmentUniformComponents = 4096; resources.maxDrawBuffers = 32; + resources.maxVertexUniformVectors = 128; + resources.maxVaryingVectors = 8; + resources.maxFragmentUniformVectors = 16; + resources.maxVertexOutputVectors = 16; + resources.minProgramTexelOffset = -8; + resources.maxProgramTexelOffset = 7; } int C_DECL main(int argc, char* argv[]) diff --git a/Test/comment.frag b/Test/comment.frag new file mode 100644 index 000000000..01b3f3a93 --- /dev/null +++ b/Test/comment.frag @@ -0,0 +1,12 @@ + + // +/* anotehn t* ontuh * / tnoahnt /* oo */ +/* multi line... + +ao */ +/* no escape \ +oanot */ +// escape nothing \o oeu +// escape newline \ +still in a comment + diff --git a/Test/pointCoord.frag b/Test/pointCoord.frag index 9455246a2..8dc9e746d 100644 --- a/Test/pointCoord.frag +++ b/Test/pointCoord.frag @@ -1,4 +1,4 @@ -precision mediump float; +precision highp float; uniform sampler2D sampler; diff --git a/Test/testlist b/Test/testlist index afe4f9b52..7a2be1bff 100644 --- a/Test/testlist +++ b/Test/testlist @@ -18,4 +18,5 @@ cppNest.vert cppComplexExpr.vert pointCoord.frag array.frag -array100.frag \ No newline at end of file +array100.frag +comment.frag diff --git a/glslang/Include/BaseTypes.h b/glslang/Include/BaseTypes.h index c22277cf6..c12792381 100644 --- a/glslang/Include/BaseTypes.h +++ b/glslang/Include/BaseTypes.h @@ -86,6 +86,10 @@ enum TStorageQualifier { EvqInOut, EvqConstReadOnly, + // built-ins read by vertex shader + EvqVertexId, + EvqInstanceId, + // built-ins written by vertex shader EvqPosition, EvqPointSize, @@ -119,6 +123,8 @@ __inline const char* getStorageQualifierString(TStorageQualifier q) case EvqIn: return "in"; break; case EvqOut: return "out"; break; case EvqInOut: return "inout"; break; + case EvqVertexId: return "gl_VertexId"; break; + case EvqInstanceId: return "gl_InstanceId"; break; case EvqPosition: return "gl_Position"; break; case EvqPointSize: return "gl_PointSize"; break; case EvqClipVertex: return "gl_ClipVertex"; break; diff --git a/glslang/Include/PoolAlloc.h b/glslang/Include/PoolAlloc.h index 49f17ecda..d40a6f511 100644 --- a/glslang/Include/PoolAlloc.h +++ b/glslang/Include/PoolAlloc.h @@ -257,7 +257,7 @@ struct TThreadGlobalPools TPoolAllocator* globalPoolAllocator; }; -void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator); +void SetGlobalPoolAllocatorPtr(TPoolAllocator& poolAllocator); // // This STL compatible allocator is intended to be used as the allocator diff --git a/glslang/Include/ResourceLimits.h b/glslang/Include/ResourceLimits.h index f3d1a5318..faf612681 100644 --- a/glslang/Include/ResourceLimits.h +++ b/glslang/Include/ResourceLimits.h @@ -1,5 +1,7 @@ // //Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//Copyright (C) 2013 LunarG, Inc. +// //All rights reserved. // //Redistribution and use in source and binary forms, with or without @@ -48,5 +50,11 @@ struct TBuiltInResource { int maxTextureImageUnits; int maxFragmentUniformComponents; int maxDrawBuffers; + int maxVertexUniformVectors; + int maxVaryingVectors; + int maxFragmentUniformVectors; + int maxVertexOutputVectors; + int minProgramTexelOffset; + int maxProgramTexelOffset; }; #endif // _RESOURCE_LIMITS_INCLUDED_ diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index 7f57afb54..b98d3254d 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -155,6 +155,15 @@ public: qualifier.storage = q; qualifier.precision = EpqNone; } + TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0) : + type(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), arraySizes(0), + structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), + fieldName(0), mangled(0), typeName(0) + { + qualifier.storage = q; + qualifier.precision = p; + assert(p >= 0 && p <= EpqHigh); + } explicit TType(const TPublicType &p) : type(p.type), vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), arraySizes(p.arraySizes), structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0) diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp index 5af9683ca..41b356f4f 100644 --- a/glslang/MachineIndependent/Initialize.cpp +++ b/glslang/MachineIndependent/Initialize.cpp @@ -36,14 +36,16 @@ // // Create strings that declare built-in definitions, add built-ins that -// cannot be expressed in the files, and establish mappings between +// cannot be expressed in the files, and establish mappings between // built-in functions and operators. // #include "../Include/intermediate.h" #include "Initialize.h" -void TBuiltIns::initialize() +const int FirstProfileVersion = 150; + +void TBuiltIns::initialize(int version, EProfile profile) { // // Initialize all the built-in strings for parsing. @@ -467,7 +469,7 @@ void TBuiltIns::initialize() s.append(TString("vec4 texture3D(sampler3D sampler, vec3 coord, float bias);")); s.append(TString("vec4 texture3DProj(sampler3D sampler, vec4 coord, float bias);")); s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord, float bias);")); - + s.append(TString("vec4 shadow1D(sampler1DShadow sampler, vec3 coord, float bias);")); s.append(TString("vec4 shadow2D(sampler2DShadow sampler, vec3 coord, float bias);")); s.append(TString("vec4 shadow1DProj(sampler1DShadow sampler, vec4 coord, float bias);")); @@ -498,185 +500,208 @@ void TBuiltIns::initialize() //============================================================================ TString& s = StandardUniforms; - - - // - // OpenGL'uniform' state. Page numbers are in reference to version - // 1.4 of the OpenGL specification. - // - - // - // Matrix state. p. 31, 32, 37, 39, 40. - // - s.append(TString("uniform mat4 gl_ModelViewMatrix;")); - s.append(TString("uniform mat4 gl_ProjectionMatrix;")); - s.append(TString("uniform mat4 gl_ModelViewProjectionMatrix;")); - - // - // Derived matrix state that provides inverse and transposed versions - // of the matrices above. - // - s.append(TString("uniform mat3 gl_NormalMatrix;")); - - s.append(TString("uniform mat4 gl_ModelViewMatrixInverse;")); - s.append(TString("uniform mat4 gl_ProjectionMatrixInverse;")); - s.append(TString("uniform mat4 gl_ModelViewProjectionMatrixInverse;")); - - s.append(TString("uniform mat4 gl_ModelViewMatrixTranspose;")); - s.append(TString("uniform mat4 gl_ProjectionMatrixTranspose;")); - s.append(TString("uniform mat4 gl_ModelViewProjectionMatrixTranspose;")); - - s.append(TString("uniform mat4 gl_ModelViewMatrixInverseTranspose;")); - s.append(TString("uniform mat4 gl_ProjectionMatrixInverseTranspose;")); - s.append(TString("uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose;")); - - // - // Normal scaling p. 39. - // - s.append(TString("uniform float gl_NormalScale;")); // // Depth range in window coordinates, p. 33 // s.append(TString("struct gl_DepthRangeParameters {")); - s.append(TString(" float near;")); // n - s.append(TString(" float far;")); // f - s.append(TString(" float diff;")); // f - n + if (profile == EEsProfile) { + s.append(TString(" highp float near;")); // n + s.append(TString(" highp float far;")); // f + s.append(TString(" highp float diff;")); // f - n + } else { + s.append(TString(" float near;")); // n + s.append(TString(" float far;")); // f + s.append(TString(" float diff;")); // f - n + } s.append(TString("};")); s.append(TString("uniform gl_DepthRangeParameters gl_DepthRange;")); + if (profile != EEsProfile && (version < FirstProfileVersion || profile == ECompatibilityProfile)) { + // + // Matrix state. p. 31, 32, 37, 39, 40. + // + s.append(TString("uniform mat4 gl_ModelViewMatrix;")); + s.append(TString("uniform mat4 gl_ProjectionMatrix;")); + s.append(TString("uniform mat4 gl_ModelViewProjectionMatrix;")); - // - // Point Size, p. 66, 67. - // - s.append(TString("struct gl_PointParameters {")); - s.append(TString(" float size;")); - s.append(TString(" float sizeMin;")); - s.append(TString(" float sizeMax;")); - s.append(TString(" float fadeThresholdSize;")); - s.append(TString(" float distanceConstantAttenuation;")); - s.append(TString(" float distanceLinearAttenuation;")); - s.append(TString(" float distanceQuadraticAttenuation;")); - s.append(TString("};")); - - s.append(TString("uniform gl_PointParameters gl_Point;")); + // + // Derived matrix state that provides inverse and transposed versions + // of the matrices above. + // + s.append(TString("uniform mat3 gl_NormalMatrix;")); - // - // Material State p. 50, 55. - // - s.append(TString("struct gl_MaterialParameters {")); - s.append(TString(" vec4 emission;")); // Ecm - s.append(TString(" vec4 ambient;")); // Acm - s.append(TString(" vec4 diffuse;")); // Dcm - s.append(TString(" vec4 specular;")); // Scm - s.append(TString(" float shininess;")); // Srm - s.append(TString("};")); - s.append(TString("uniform gl_MaterialParameters gl_FrontMaterial;")); - s.append(TString("uniform gl_MaterialParameters gl_BackMaterial;")); + s.append(TString("uniform mat4 gl_ModelViewMatrixInverse;")); + s.append(TString("uniform mat4 gl_ProjectionMatrixInverse;")); + s.append(TString("uniform mat4 gl_ModelViewProjectionMatrixInverse;")); - // - // Light State p 50, 53, 55. - // + s.append(TString("uniform mat4 gl_ModelViewMatrixTranspose;")); + s.append(TString("uniform mat4 gl_ProjectionMatrixTranspose;")); + s.append(TString("uniform mat4 gl_ModelViewProjectionMatrixTranspose;")); - s.append(TString("struct gl_LightSourceParameters {")); - s.append(TString(" vec4 ambient;")); // Acli - s.append(TString(" vec4 diffuse;")); // Dcli - s.append(TString(" vec4 specular;")); // Scli - s.append(TString(" vec4 position;")); // Ppli - s.append(TString(" vec4 halfVector;")); // Derived: Hi - s.append(TString(" vec3 spotDirection;")); // Sdli - s.append(TString(" float spotExponent;")); // Srli - s.append(TString(" float spotCutoff;")); // Crli - // (range: [0.0,90.0], 180.0) - s.append(TString(" float spotCosCutoff;")); // Derived: cos(Crli) - // (range: [1.0,0.0],-1.0) - s.append(TString(" float constantAttenuation;")); // K0 - s.append(TString(" float linearAttenuation;")); // K1 - s.append(TString(" float quadraticAttenuation;"));// K2 - s.append(TString("};")); + s.append(TString("uniform mat4 gl_ModelViewMatrixInverseTranspose;")); + s.append(TString("uniform mat4 gl_ProjectionMatrixInverseTranspose;")); + s.append(TString("uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose;")); + + // + // Normal scaling p. 39. + // + s.append(TString("uniform float gl_NormalScale;")); + + // + // Point Size, p. 66, 67. + // + s.append(TString("struct gl_PointParameters {")); + s.append(TString(" float size;")); + s.append(TString(" float sizeMin;")); + s.append(TString(" float sizeMax;")); + s.append(TString(" float fadeThresholdSize;")); + s.append(TString(" float distanceConstantAttenuation;")); + s.append(TString(" float distanceLinearAttenuation;")); + s.append(TString(" float distanceQuadraticAttenuation;")); + s.append(TString("};")); + + s.append(TString("uniform gl_PointParameters gl_Point;")); + + // + // Material State p. 50, 55. + // + s.append(TString("struct gl_MaterialParameters {")); + s.append(TString(" vec4 emission;")); // Ecm + s.append(TString(" vec4 ambient;")); // Acm + s.append(TString(" vec4 diffuse;")); // Dcm + s.append(TString(" vec4 specular;")); // Scm + s.append(TString(" float shininess;")); // Srm + s.append(TString("};")); + s.append(TString("uniform gl_MaterialParameters gl_FrontMaterial;")); + s.append(TString("uniform gl_MaterialParameters gl_BackMaterial;")); + + // + // Light State p 50, 53, 55. + // + + s.append(TString("struct gl_LightSourceParameters {")); + s.append(TString(" vec4 ambient;")); // Acli + s.append(TString(" vec4 diffuse;")); // Dcli + s.append(TString(" vec4 specular;")); // Scli + s.append(TString(" vec4 position;")); // Ppli + s.append(TString(" vec4 halfVector;")); // Derived: Hi + s.append(TString(" vec3 spotDirection;")); // Sdli + s.append(TString(" float spotExponent;")); // Srli + s.append(TString(" float spotCutoff;")); // Crli + // (range: [0.0,90.0], 180.0) + s.append(TString(" float spotCosCutoff;")); // Derived: cos(Crli) + // (range: [1.0,0.0],-1.0) + s.append(TString(" float constantAttenuation;")); // K0 + s.append(TString(" float linearAttenuation;")); // K1 + s.append(TString(" float quadraticAttenuation;"));// K2 + s.append(TString("};")); - s.append(TString("struct gl_LightModelParameters {")); - s.append(TString(" vec4 ambient;")); // Acs - s.append(TString("};")); + s.append(TString("struct gl_LightModelParameters {")); + s.append(TString(" vec4 ambient;")); // Acs + s.append(TString("};")); - s.append(TString("uniform gl_LightModelParameters gl_LightModel;")); + s.append(TString("uniform gl_LightModelParameters gl_LightModel;")); - // - // Derived state from products of light and material. - // + // + // Derived state from products of light and material. + // - s.append(TString("struct gl_LightModelProducts {")); - s.append(TString(" vec4 sceneColor;")); // Derived. Ecm + Acm * Acs - s.append(TString("};")); + s.append(TString("struct gl_LightModelProducts {")); + s.append(TString(" vec4 sceneColor;")); // Derived. Ecm + Acm * Acs + s.append(TString("};")); - s.append(TString("uniform gl_LightModelProducts gl_FrontLightModelProduct;")); - s.append(TString("uniform gl_LightModelProducts gl_BackLightModelProduct;")); + s.append(TString("uniform gl_LightModelProducts gl_FrontLightModelProduct;")); + s.append(TString("uniform gl_LightModelProducts gl_BackLightModelProduct;")); - s.append(TString("struct gl_LightProducts {")); - s.append(TString(" vec4 ambient;")); // Acm * Acli - s.append(TString(" vec4 diffuse;")); // Dcm * Dcli - s.append(TString(" vec4 specular;")); // Scm * Scli - s.append(TString("};")); + s.append(TString("struct gl_LightProducts {")); + s.append(TString(" vec4 ambient;")); // Acm * Acli + s.append(TString(" vec4 diffuse;")); // Dcm * Dcli + s.append(TString(" vec4 specular;")); // Scm * Scli + s.append(TString("};")); + // + // Fog p. 161 + // + s.append(TString("struct gl_FogParameters {")); + s.append(TString(" vec4 color;")); + s.append(TString(" float density;")); + s.append(TString(" float start;")); + s.append(TString(" float end;")); + s.append(TString(" float scale;")); // 1 / (gl_FogEnd - gl_FogStart) + s.append(TString("};")); - - - // - // Fog p. 161 - // - s.append(TString("struct gl_FogParameters {")); - s.append(TString(" vec4 color;")); - s.append(TString(" float density;")); - s.append(TString(" float start;")); - s.append(TString(" float end;")); - s.append(TString(" float scale;")); // 1 / (gl_FogEnd - gl_FogStart) - s.append(TString("};")); - - s.append(TString("uniform gl_FogParameters gl_Fog;")); + s.append(TString("uniform gl_FogParameters gl_Fog;")); + } s.append(TString("\n")); } - { - //============================================================================ - // - // Vertex attributes, p. 19. - // - //============================================================================ + //============================================================================ + // + // Vertex attributes, p. 19. + // + //============================================================================ + if (profile != EEsProfile) { TString& s = StandardVertexAttributes; - s.append(TString("attribute vec4 gl_Color;")); - s.append(TString("attribute vec4 gl_SecondaryColor;")); - s.append(TString("attribute vec3 gl_Normal;")); - s.append(TString("attribute vec4 gl_Vertex;")); - s.append(TString("attribute vec4 gl_MultiTexCoord0;")); - s.append(TString("attribute vec4 gl_MultiTexCoord1;")); - s.append(TString("attribute vec4 gl_MultiTexCoord2;")); - s.append(TString("attribute vec4 gl_MultiTexCoord3;")); - s.append(TString("attribute vec4 gl_MultiTexCoord4;")); - s.append(TString("attribute vec4 gl_MultiTexCoord5;")); - s.append(TString("attribute vec4 gl_MultiTexCoord6;")); - s.append(TString("attribute vec4 gl_MultiTexCoord7;")); - s.append(TString("attribute float gl_FogCoord;")); + if (version < 130) { + s.append(TString("attribute vec4 gl_Color;")); + s.append(TString("attribute vec4 gl_SecondaryColor;")); + s.append(TString("attribute vec3 gl_Normal;")); + s.append(TString("attribute vec4 gl_Vertex;")); + s.append(TString("attribute vec4 gl_MultiTexCoord0;")); + s.append(TString("attribute vec4 gl_MultiTexCoord1;")); + s.append(TString("attribute vec4 gl_MultiTexCoord2;")); + s.append(TString("attribute vec4 gl_MultiTexCoord3;")); + s.append(TString("attribute vec4 gl_MultiTexCoord4;")); + s.append(TString("attribute vec4 gl_MultiTexCoord5;")); + s.append(TString("attribute vec4 gl_MultiTexCoord6;")); + s.append(TString("attribute vec4 gl_MultiTexCoord7;")); + s.append(TString("attribute float gl_FogCoord;")); + } else if (version < FirstProfileVersion || profile == ECompatibilityProfile) { + s.append(TString("in vec4 gl_Color;")); + s.append(TString("in vec4 gl_SecondaryColor;")); + s.append(TString("in vec3 gl_Normal;")); + s.append(TString("in vec4 gl_Vertex;")); + s.append(TString("in vec4 gl_MultiTexCoord0;")); + s.append(TString("in vec4 gl_MultiTexCoord1;")); + s.append(TString("in vec4 gl_MultiTexCoord2;")); + s.append(TString("in vec4 gl_MultiTexCoord3;")); + s.append(TString("in vec4 gl_MultiTexCoord4;")); + s.append(TString("in vec4 gl_MultiTexCoord5;")); + s.append(TString("in vec4 gl_MultiTexCoord6;")); + s.append(TString("in vec4 gl_MultiTexCoord7;")); + s.append(TString("in float gl_FogCoord;")); + } s.append(TString("\n")); } - { - //============================================================================ - // - // Define the output varying interface from the vertex shader. - // - //============================================================================ + //============================================================================ + // + // Define the output varying interface from the vertex shader. + // + //============================================================================ + if (profile != EEsProfile) { TString& s = StandardVertexVaryings; - s.append(TString("varying vec4 gl_FrontColor;")); - s.append(TString("varying vec4 gl_BackColor;")); - s.append(TString("varying vec4 gl_FrontSecondaryColor;")); - s.append(TString("varying vec4 gl_BackSecondaryColor;")); - s.append(TString("varying vec4 gl_TexCoord[];")); - s.append(TString("varying float gl_FogFragCoord;")); + if (version < 130) { + s.append(TString("varying vec4 gl_FrontColor;")); + s.append(TString("varying vec4 gl_BackColor;")); + s.append(TString("varying vec4 gl_FrontSecondaryColor;")); + s.append(TString("varying vec4 gl_BackSecondaryColor;")); + s.append(TString("varying vec4 gl_TexCoord[];")); + s.append(TString("varying float gl_FogFragCoord;")); + } else if (version < FirstProfileVersion || profile == ECompatibilityProfile) { + s.append(TString("out vec4 gl_FrontColor;")); + s.append(TString("out vec4 gl_BackColor;")); + s.append(TString("out vec4 gl_FrontSecondaryColor;")); + s.append(TString("out vec4 gl_BackSecondaryColor;")); + s.append(TString("out vec4 gl_TexCoord[];")); + s.append(TString("out float gl_FogFragCoord;")); + } s.append(TString("\n")); } @@ -687,14 +712,22 @@ void TBuiltIns::initialize() // //============================================================================ - TString& s = StandardFragmentVaryings; + if (profile != EEsProfile) { + TString& s = StandardFragmentVaryings; + if (version < 130) { + s.append(TString("varying vec4 gl_Color;")); + s.append(TString("varying vec4 gl_SecondaryColor;")); + s.append(TString("varying vec4 gl_TexCoord[];")); + s.append(TString("varying float gl_FogFragCoord;")); + } else if (version < FirstProfileVersion || profile == ECompatibilityProfile) { + s.append(TString("in vec4 gl_Color;")); + s.append(TString("in vec4 gl_SecondaryColor;")); + s.append(TString("in vec4 gl_TexCoord[];")); + s.append(TString("in float gl_FogFragCoord;")); + } - s.append(TString("varying vec4 gl_Color;")); - s.append(TString("varying vec4 gl_SecondaryColor;")); - s.append(TString("varying vec4 gl_TexCoord[];")); - s.append(TString("varying float gl_FogFragCoord;")); - - s.append(TString("\n")); + s.append(TString("\n")); + } } builtInStrings[EShLangFragment].push_back(BuiltInFunctions.c_str()); @@ -710,12 +743,12 @@ void TBuiltIns::initialize() } -void TBuiltIns::initialize(const TBuiltInResource &resources) +void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProfile profile, EShLanguage language) { // // Initialize the context-dependent (resource-dependent) built-in strings for parsing. // - TString StandardUniforms; + TString StandardUniforms; { //============================================================================ @@ -725,97 +758,137 @@ void TBuiltIns::initialize(const TBuiltInResource &resources) //============================================================================ TString& s = StandardUniforms; - + const int maxSize = 80; + char builtInConstant[maxSize]; + // // Implementation dependent constants. The example values below // are the minimum values allowed for these maximums. // - const int maxSize = 80; - char builtInConstant[maxSize]; - snprintf(builtInConstant, maxSize, "const int gl_MaxLights = %d;", resources.maxLights); // GL 1.0 - s.append(TString(builtInConstant)); - - snprintf(builtInConstant, maxSize, "const int gl_MaxClipPlanes = %d;", resources.maxClipPlanes); // GL 1.0 - s.append(TString(builtInConstant)); - - snprintf(builtInConstant, maxSize, "const int gl_MaxTextureUnits = %d;", resources.maxTextureUnits); // GL 1.2 - s.append(TString(builtInConstant)); - - snprintf(builtInConstant, maxSize, "const int gl_MaxTextureCoords = %d;", resources.maxTextureCoords); // ARB_fragment_program - s.append(TString(builtInConstant)); - - snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs); // ARB_vertex_shader - s.append(TString(builtInConstant)); - - snprintf(builtInConstant, maxSize, "const int gl_MaxVertexUniformComponents = %d;", resources.maxVertexUniformComponents); // ARB_vertex_shader - s.append(TString(builtInConstant)); - - snprintf(builtInConstant, maxSize, "const int gl_MaxVaryingFloats = %d;", resources.maxVaryingFloats); // ARB_vertex_shader - s.append(TString(builtInConstant)); - - snprintf(builtInConstant, maxSize, "const int gl_MaxVertexTextureImageUnits = %d;", resources.maxVertexTextureImageUnits); // ARB_vertex_shader - s.append(TString(builtInConstant)); - - snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedTextureImageUnits = %d;", resources.maxCombinedTextureImageUnits); // ARB_vertex_shader - s.append(TString(builtInConstant)); - - snprintf(builtInConstant, maxSize, "const int gl_MaxTextureImageUnits = %d;", resources.maxTextureImageUnits); // ARB_fragment_shader - s.append(TString(builtInConstant)); - - snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentUniformComponents = %d;", resources.maxFragmentUniformComponents); // ARB_fragment_shader - s.append(TString(builtInConstant)); - - snprintf(builtInConstant, maxSize, "const int gl_MaxDrawBuffers = %d;", resources.maxDrawBuffers); // proposed ARB_draw_buffers - s.append(TString(builtInConstant)); - // - // OpenGL'uniform' state. Page numbers are in reference to version - // 1.4 of the OpenGL specification. - // + if (profile == EEsProfile) { + snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs); + s.append(TString(builtInConstant)); - // - // Matrix state. p. 31, 32, 37, 39, 40. - // - s.append(TString("uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];")); + snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexUniformVectors = %d;", resources.maxVertexUniformVectors); + s.append(TString(builtInConstant)); - // - // Derived matrix state that provides inverse and transposed versions - // of the matrices above. - // - s.append(TString("uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords];")); + snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexTextureImageUnits = %d;", resources.maxVertexTextureImageUnits); + s.append(TString(builtInConstant)); - s.append(TString("uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords];")); + snprintf(builtInConstant, maxSize, "const mediump int gl_MaxCombinedTextureImageUnits = %d;", resources.maxCombinedTextureImageUnits); + s.append(TString(builtInConstant)); - s.append(TString("uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords];")); + snprintf(builtInConstant, maxSize, "const mediump int gl_MaxTextureImageUnits = %d;", resources.maxTextureImageUnits); + s.append(TString(builtInConstant)); + + snprintf(builtInConstant, maxSize, "const mediump int gl_MaxFragmentUniformVectors = %d;", resources.maxFragmentUniformVectors); + s.append(TString(builtInConstant)); - // - // Clip planes p. 42. - // - s.append(TString("uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];")); + snprintf(builtInConstant, maxSize, "const mediump int gl_MaxDrawBuffers = %d;", resources.maxDrawBuffers); + s.append(TString(builtInConstant)); - // - // Light State p 50, 53, 55. - // - s.append(TString("uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];")); + if (version == 100) { + snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVaryingVectors = %d;", resources.maxVaryingVectors); + s.append(TString(builtInConstant)); + } else { + snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexOutputVectors = %d;", resources.maxVertexOutputVectors); + s.append(TString(builtInConstant)); - // - // Derived state from products of light. - // - s.append(TString("uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];")); - s.append(TString("uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];")); + snprintf(builtInConstant, maxSize, "const mediump int gl_MinProgramTexelOffset = %d;", resources.minProgramTexelOffset); + s.append(TString(builtInConstant)); + + snprintf(builtInConstant, maxSize, "const mediump int gl_MaxProgramTexelOffset = %d;", resources.maxProgramTexelOffset); + s.append(TString(builtInConstant)); + } + } else { + snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs); + s.append(TString(builtInConstant)); - // - // Textureg Environment and Generation, p. 152, p. 40-42. - // - s.append(TString("uniform vec4 gl_TextureEnvColor[gl_MaxTextureImageUnits];")); - s.append(TString("uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords];")); - s.append(TString("uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords];")); - s.append(TString("uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords];")); - s.append(TString("uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords];")); - s.append(TString("uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords];")); - s.append(TString("uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords];")); - s.append(TString("uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords];")); - s.append(TString("uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords];")); + snprintf(builtInConstant, maxSize, "const int gl_MaxVertexTextureImageUnits = %d;", resources.maxVertexTextureImageUnits); + s.append(TString(builtInConstant)); + + snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedTextureImageUnits = %d;", resources.maxCombinedTextureImageUnits); + s.append(TString(builtInConstant)); + + snprintf(builtInConstant, maxSize, "const int gl_MaxTextureImageUnits = %d;", resources.maxTextureImageUnits); + s.append(TString(builtInConstant)); + + snprintf(builtInConstant, maxSize, "const int gl_MaxDrawBuffers = %d;", resources.maxDrawBuffers); + s.append(TString(builtInConstant)); + + snprintf(builtInConstant, maxSize, "const int gl_MaxLights = %d;", resources.maxLights); + s.append(TString(builtInConstant)); + + snprintf(builtInConstant, maxSize, "const int gl_MaxClipPlanes = %d;", resources.maxClipPlanes); + s.append(TString(builtInConstant)); + + snprintf(builtInConstant, maxSize, "const int gl_MaxTextureUnits = %d;", resources.maxTextureUnits); + s.append(TString(builtInConstant)); + + snprintf(builtInConstant, maxSize, "const int gl_MaxTextureCoords = %d;", resources.maxTextureCoords); + s.append(TString(builtInConstant)); + + snprintf(builtInConstant, maxSize, "const int gl_MaxVertexUniformComponents = %d;", resources.maxVertexUniformComponents); + s.append(TString(builtInConstant)); + + snprintf(builtInConstant, maxSize, "const int gl_MaxVaryingFloats = %d;", resources.maxVaryingFloats); + s.append(TString(builtInConstant)); + + snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentUniformComponents = %d;", resources.maxFragmentUniformComponents); + s.append(TString(builtInConstant)); + + if (version < FirstProfileVersion || profile == ECompatibilityProfile) { + // + // OpenGL'uniform' state. Page numbers are in reference to version + // 1.4 of the OpenGL specification. + // + + // + // Matrix state. p. 31, 32, 37, 39, 40. + // + s.append(TString("uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];")); + + // + // Derived matrix state that provides inverse and transposed versions + // of the matrices above. + // + s.append(TString("uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords];")); + + s.append(TString("uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords];")); + + s.append(TString("uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords];")); + + // + // Clip planes p. 42. + // + s.append(TString("uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];")); + + // + // Light State p 50, 53, 55. + // + s.append(TString("uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];")); + + // + // Derived state from products of light. + // + s.append(TString("uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];")); + s.append(TString("uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];")); + + // + // Textureg Environment and Generation, p. 152, p. 40-42. + // + s.append(TString("uniform vec4 gl_TextureEnvColor[gl_MaxTextureImageUnits];")); + s.append(TString("uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords];")); + s.append(TString("uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords];")); + s.append(TString("uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords];")); + s.append(TString("uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords];")); + s.append(TString("uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords];")); + s.append(TString("uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords];")); + s.append(TString("uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords];")); + s.append(TString("uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords];")); + } + } s.append(TString("\n")); } @@ -824,28 +897,57 @@ void TBuiltIns::initialize(const TBuiltInResource &resources) builtInStrings[EShLangVertex].push_back(StandardUniforms); } -void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable) +void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymbolTable& symbolTable) { + TPrecisionQualifier pq; // - // First, insert some special built-in variables that are not in - // the built-in header files. + // First, insert some special built-in variables that are not in + // the built-in text strings. // switch(language) { case EShLangFragment: - symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EvqFace, 1))); - symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EvqFragCoord, 4))); - symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EvqPointCoord, 2))); + symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EvqFace, 1))); - symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EvqFragColor, 4))); - symbolTable.insert(*new TVariable(NewPoolTString("gl_FragDepth"), TType(EbtFloat, EvqFragDepth, 1))); + if (profile == EEsProfile) + pq = version == 100 ? EpqMedium : EpqHigh; + else + pq = EpqNone; + symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EvqFragCoord, pq, 4))); + + if (profile == EEsProfile || version >= 120) { + pq = profile == EEsProfile ? EpqMedium : EpqNone; + symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EvqPointCoord, pq, 2))); + } + + if (version < FirstProfileVersion || profile == ECompatibilityProfile) { + pq = profile == EEsProfile ? EpqMedium : EpqNone; + symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EvqFragColor, pq, 4))); + } + + if (profile != EEsProfile || version > 100) { + pq = profile == EEsProfile ? EpqHigh : EpqNone; + symbolTable.insert(*new TVariable(NewPoolTString("gl_FragDepth"), TType(EbtFloat, EvqFragDepth, pq, 1))); + } break; case EShLangVertex: - symbolTable.insert(*new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EvqPosition, 4))); - symbolTable.insert(*new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EvqPointSize, 1))); - symbolTable.insert(*new TVariable(NewPoolTString("gl_ClipVertex"), TType(EbtFloat, EvqClipVertex, 4))); + pq = profile == EEsProfile ? EpqHigh : EpqNone; + symbolTable.insert(*new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EvqPosition, pq, 4))); + + pq = profile == EEsProfile ? (version > 100 ? EpqHigh : EpqMedium) : EpqNone; + symbolTable.insert(*new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EvqPointSize, pq, 1))); + + if (profile != EEsProfile) + symbolTable.insert(*new TVariable(NewPoolTString("gl_ClipVertex"), TType(EbtFloat, EvqClipVertex, 4))); + + if (version >= 130) { + pq = profile == EEsProfile ? EpqHigh : EpqNone; + symbolTable.insert(*new TVariable(NewPoolTString("gl_VertexID"), TType(EbtInt, EvqVertexId, pq, 1))); + if (version >= 140) + symbolTable.insert(*new TVariable(NewPoolTString("gl_InstanceID"), TType(EbtInt, EvqInstanceId, pq, 1))); + } break; - + case EShLangTessControl: case EShLangTessEvaluation: case EShLangGeometry: @@ -870,7 +972,7 @@ void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable) symbolTable.relateToOperator("greaterThan", EOpGreaterThan); symbolTable.relateToOperator("lessThanEqual", EOpLessThanEqual); symbolTable.relateToOperator("greaterThanEqual", EOpGreaterThanEqual); - + symbolTable.relateToOperator("radians", EOpRadians); symbolTable.relateToOperator("degrees", EOpDegrees); symbolTable.relateToOperator("sin", EOpSin); @@ -908,7 +1010,7 @@ void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable) symbolTable.relateToOperator("faceforward", EOpFaceForward); symbolTable.relateToOperator("reflect", EOpReflect); symbolTable.relateToOperator("refract", EOpRefract); - + symbolTable.relateToOperator("any", EOpAny); symbolTable.relateToOperator("all", EOpAll); @@ -916,10 +1018,10 @@ void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable) case EShLangVertex: break; - + case EShLangFragment: - symbolTable.relateToOperator("dFdx", EOpDPdx); - symbolTable.relateToOperator("dFdy", EOpDPdy); + symbolTable.relateToOperator("dFdx", EOpDPdx); + symbolTable.relateToOperator("dFdy", EOpDPdy); symbolTable.relateToOperator("fwidth", EOpFwidth); break; @@ -928,16 +1030,17 @@ void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable) } } -void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources) +void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources) { // - // First, insert some special built-in variables that are not in - // the built-in header files. + // Set resource-specific built-ins not yet handled. // switch(language) { - case EShLangFragment: { - // Set up gl_FragData. The array size. + case EShLangFragment: + // Set up gl_FragData based on current array size. + if (version < FirstProfileVersion || profile == ECompatibilityProfile) { + TPrecisionQualifier pq = profile == EEsProfile ? EpqMedium : EpqNone; TType fragData(EbtFloat, EvqFragColor, 4); TArraySizes arraySizes = NewPoolTArraySizes(); arraySizes->push_back(resources.maxDrawBuffers); diff --git a/glslang/MachineIndependent/Initialize.h b/glslang/MachineIndependent/Initialize.h index e427ee136..58cf6470f 100644 --- a/glslang/MachineIndependent/Initialize.h +++ b/glslang/MachineIndependent/Initialize.h @@ -1,5 +1,7 @@ // //Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//Copyright (C) 2013 LunarG, Inc. +// //All rights reserved. // //Redistribution and use in source and binary forms, with or without @@ -39,23 +41,22 @@ #include "../Include/Common.h" #include "../Include/ShHandle.h" #include "SymbolTable.h" +#include "Versions.h" typedef TVector TBuiltInStrings; class TBuiltIns { public: POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) - void initialize(); - void initialize(const TBuiltInResource& resources); + void initialize(int version, EProfile); + void initialize(const TBuiltInResource& resources, int version, EProfile, EShLanguage); TBuiltInStrings* getBuiltInStrings() { return builtInStrings; } protected: TBuiltInStrings builtInStrings[EShLangCount]; }; -void IdentifyBuiltIns(EShLanguage, TSymbolTable&); -void IdentifyBuiltIns(EShLanguage, TSymbolTable&, const TBuiltInResource &resources); -bool GenerateBuiltInSymbolTable(const TBuiltInResource* resources, TInfoSink&, TSymbolTable*, EShLanguage language = EShLangCount); -bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, EShLanguage language, TInfoSink& infoSink, const TBuiltInResource *resources, TSymbolTable*); +void IdentifyBuiltIns(int version, EProfile profile, EShLanguage, TSymbolTable&); +void IdentifyBuiltIns(int version, EProfile profile, EShLanguage, TSymbolTable&, const TBuiltInResource &resources); extern "C" int InitPreprocessor(void); extern "C" int FinalizePreprocessor(void); diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 3b0bc4e34..4814fbecc 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -38,95 +38,43 @@ #include "Include/InitializeParseContext.h" #include "osinclude.h" #include + +TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, int v, EProfile p, EShLanguage L, TInfoSink& is) : + intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0), + recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0), + switchNestingLevel(0), inTypeParen(false), + version(v), profile(p), futureCompatibility(false), + contextPragma(true, false) +{ + for (int type = 0; type < EbtNumTypes; ++type) + defaultPrecision[type] = EpqNone; + + if (profile == EEsProfile) { + switch (language) { + case EShLangVertex: + defaultPrecision[EbtInt] = EpqHigh; + defaultPrecision[EbtFloat] = EpqHigh; + defaultPrecision[EbtSampler2D] = EpqLow; + defaultPrecision[EbtSamplerCube] = EpqLow; + break; + case EShLangFragment: + defaultPrecision[EbtInt] = EpqMedium; + defaultPrecision[EbtSampler2D] = EpqLow; + defaultPrecision[EbtSamplerCube] = EpqLow; + // TODO: give error when using float in frag shader without default precision + break; + default: + error(1, "INTERNAL ERROR", "unexpected language", ""); + } + } +} + /////////////////////////////////////////////////////////////////////// // // Sub- vector and matrix fields // //////////////////////////////////////////////////////////////////////// - -TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLanguage L, TInfoSink& is, int defaultVersion) : - intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0), - recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0), - switchNestingLevel(0), inTypeParen(false), - futureCompatibility(false), - contextPragma(true, false) -{ - // Default precisions for version 110, to be overridden for - // other versions/profiles/stage combinations - for (int type = 0; type < EbtNumTypes; ++type) - defaultPrecision[type] = EpqNone; - - setVersion(defaultVersion); - setProfile(ENoProfile); -} - -void TParseContext::setVersion(int newVersion) -{ - version = newVersion; - if (version == 100 || version == 300) { - if (language == EShLangVertex) { - defaultPrecision[EbtInt] = EpqHigh; - defaultPrecision[EbtFloat] = EpqHigh; - defaultPrecision[EbtSampler2D] = EpqLow; - defaultPrecision[EbtSamplerCube] = EpqLow; -} - - if (language == EShLangFragment) { - defaultPrecision[EbtInt] = EpqMedium; - defaultPrecision[EbtSampler2D] = EpqLow; - defaultPrecision[EbtSamplerCube] = EpqLow; - // TODO: give error when using float in frag shader without default precision - } - } else { - for (int type = 0; type < EbtNumTypes; ++type) - defaultPrecision[type] = EpqNone; - } -} - -// Important assumption: SetVersion() is called before SetProfile(), and is always called -// if there is a version, sending in a ENoProfile if there is no profile given. -void TParseContext::setProfile(EProfile newProfile) -{ - const int FirstProfileVersion = 150; - - if (newProfile == ENoProfile) { - if (version == 300) { - error(1, "version 300 requires specifying the 'es' profile", "#version", ""); - profile = EEsProfile; - } else if (version == 100) - profile = EEsProfile; - else if (version >= FirstProfileVersion) - profile = ECoreProfile; - else - profile = ENoProfile; - } else { - // a profile was provided... - if (version < 150) { - error(1, "versions before 150 do not allow a profile token", "#version", ""); - if (version == 100) - profile = EEsProfile; - else - profile = ENoProfile; - } else if (version == 300) { - if (newProfile != EEsProfile) - error(1, "only version 300 supports the es profile", "#version", ""); - profile = EEsProfile; - } else { - if (newProfile == EEsProfile) { - error(1, "only version 300 supports the es profile", "#version", ""); - if (version >= FirstProfileVersion) - profile = ECoreProfile; - else - profile = ENoProfile; - } else { - // typical desktop case... e.g., "#version 410 core" - profile = newProfile; - } - } - } -} - // // Look at a '.' field selector string and change it into offsets // for a vector. @@ -380,6 +328,8 @@ bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* nod case EvqAttribute: message = "can't modify an attribute"; break; case EvqUniform: message = "can't modify a uniform"; break; case EvqVaryingIn: message = "can't modify a varying"; break; + case EvqInstanceId: message = "can't modify gl_InstanceID"; break; + case EvqVertexId: message = "can't modify gl_VertexID"; break; case EvqFace: message = "can't modify gl_FrontFace"; break; case EvqFragCoord: message = "can't modify gl_FragCoord"; break; case EvqPointCoord: message = "can't modify gl_PointCoord"; break; @@ -767,9 +717,10 @@ bool TParseContext::insertBuiltInArrayAtGlobalLevel() { TString *name = NewPoolTString("gl_TexCoord"); TSymbol* symbol = symbolTable.find(*name); - if (!symbol) { - error(0, "INTERNAL ERROR finding symbol", name->c_str(), ""); - return true; + if (! symbol) { + // assume it was not added due to version/profile + + return false; } TVariable* variable = symbol->getAsVariable(); diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 8ed61a63f..c57ce3275 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -67,9 +67,9 @@ struct TPragma { // they can be passed to the parser without needing a global. // struct TParseContext { - TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLanguage L, TInfoSink& is, int defaultVersion); + TParseContext(TSymbolTable&, TIntermediate&, int version, EProfile, EShLanguage, TInfoSink&); TIntermediate& intermediate; // to hold and build a parse tree - TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed + TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile TInfoSink& infoSink; EShLanguage language; // vertex or fragment language TIntermNode* treeRoot; // root of parse tree being created @@ -92,9 +92,6 @@ struct TParseContext { TString HashErrMsg; bool AfterEOF; - void setVersion(int); - void setProfile(EProfile); - void initializeExtensionBehavior(); void C_DECL error(TSourceLoc, const char *szReason, const char *szToken, diff --git a/glslang/MachineIndependent/PoolAlloc.cpp b/glslang/MachineIndependent/PoolAlloc.cpp index 2ff113b7d..53bfe28f0 100644 --- a/glslang/MachineIndependent/PoolAlloc.cpp +++ b/glslang/MachineIndependent/PoolAlloc.cpp @@ -52,8 +52,7 @@ void InitializeGlobalPools() threadData->globalPoolAllocator = globalPoolAllocator; - OS_SetTLSValue(PoolIndex, threadData); - globalPoolAllocator->push(); + OS_SetTLSValue(PoolIndex, threadData); } void FreeGlobalPools() @@ -90,11 +89,11 @@ TPoolAllocator& GetGlobalPoolAllocator() return *threadData->globalPoolAllocator; } -void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator) +void SetGlobalPoolAllocatorPtr(TPoolAllocator& poolAllocator) { TThreadGlobalPools* threadData = static_cast(OS_GetTLSValue(PoolIndex)); - threadData->globalPoolAllocator = poolAllocator; + threadData->globalPoolAllocator = &poolAllocator; } // @@ -143,6 +142,8 @@ TPoolAllocator::TPoolAllocator(bool g, int growthIncrement, int allocationAlignm if (headerSkip < sizeof(tHeader)) { headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask; } + + push(); } TPoolAllocator::~TPoolAllocator() diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index dce988747..6b416fb67 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -1,5 +1,7 @@ // //Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//Copyright (C) 2013 LunarG, Inc. +// //All rights reserved. // //Redistribution and use in source and binary forms, with or without @@ -35,7 +37,10 @@ // // Implement the top-level of interface to the compiler/linker, // as defined in ShaderLang.h +// This is the platform independent interface between an OGL driver +// and the shading language compiler/linker. // + #include "SymbolTable.h" #include "ParseHelper.h" @@ -45,61 +50,355 @@ #define SH_EXPORTING #include "../Public/ShaderLang.h" #include "Initialize.h" + +namespace { // anonymous namespace for file-local functions and symbols + +int MapVersionToIndex(int version) +{ + switch(version) { + case 100: return 0; + case 110: return 1; + case 120: return 2; + case 130: return 3; + case 140: return 4; + case 150: return 5; + case 300: return 6; + case 330: return 7; + case 400: return 8; + case 410: return 9; + case 420: return 10; + case 430: return 11; + default: // | + return 0; // | + } // | +} // V +const int VersionCount = 12; + // -// A symbol table for each language. Each has a different -// set of built-ins, and we want to preserve that from +// A symbol table per version per profile per language. This will be sparsely +// populated, so they will only only be generated as needed. +// +// Each has a different set of built-ins, and we want to preserve that from // compile to compile. // -TSymbolTable SymbolTables[EShLangCount]; - +// TODO: thread safety: ensure the built-in symbol table levels are reado only. +TSymbolTable* SharedSymbolTables[VersionCount][EProfileCount][EShLangCount] = {}; TPoolAllocator* PerProcessGPA = 0; -// -// This is the platform independent interface between an OGL driver -// and the shading language compiler/linker. -// + +bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, int version, EProfile profile, EShLanguage language, TInfoSink& infoSink, + const TBuiltInResource* resources, TSymbolTable* symbolTables) +{ + TIntermediate intermediate(infoSink); + TSymbolTable* symbolTable; + + if (resources) + symbolTable = symbolTables; + else + symbolTable = &symbolTables[language]; + + TParseContext parseContext(*symbolTable, intermediate, version, profile, language, infoSink); + + GlobalParseContext = &parseContext; + + assert(symbolTable->isEmpty() || symbolTable->atSharedBuiltInLevel()); + + // + // Parse the built-ins. This should only happen once per + // language symbol table when no 'resources' are passed in. + // + // Push the symbol table to give it an initial scope. This + // push should not have a corresponding pop, so that built-ins + // are preserved, and the test for an empty table fails. + // + + symbolTable->push(); + + + //Initialize the Preprocessor + int ret = InitPreprocessor(); + if (ret) { + infoSink.info.message(EPrefixInternalError, "Unable to intialize the Preprocessor"); + return false; + } + + ResetFlex(); + + for (TBuiltInStrings::iterator i = BuiltInStrings[parseContext.language].begin(); + i != BuiltInStrings[parseContext.language].end(); ++i) { + const char* builtInShaders[1]; + int builtInLengths[1]; + + builtInShaders[0] = (*i).c_str(); + builtInLengths[0] = (int) (*i).size(); + + if (PaParseStrings(const_cast(builtInShaders), builtInLengths, 1, parseContext) != 0) { + infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins"); + + return false; + } + } + FinalizePreprocessor(); + + if (resources) { + IdentifyBuiltIns(version, profile, parseContext.language, *symbolTable, *resources); + } else { + IdentifyBuiltIns(version, profile, parseContext.language, *symbolTable); + } + return true; +} + +bool GenerateBuiltInSymbolTable(TInfoSink& infoSink, TSymbolTable* symbolTables, int version, EProfile profile) +{ + TBuiltIns builtIns; + + builtIns.initialize(version, profile); + InitializeSymbolTable(builtIns.getBuiltInStrings(), version, profile, EShLangVertex, infoSink, 0, symbolTables); + InitializeSymbolTable(builtIns.getBuiltInStrings(), version, profile, EShLangFragment, infoSink, 0, symbolTables); + + return true; +} + +bool AddContextSpecificSymbols(const TBuiltInResource* resources, TInfoSink& infoSink, TSymbolTable* symbolTables, int version, EProfile profile, EShLanguage language) +{ + TBuiltIns builtIns; + + builtIns.initialize(*resources, version, profile, language); + InitializeSymbolTable(builtIns.getBuiltInStrings(), version, profile, language, infoSink, resources, symbolTables); + + return true; +} // // Driver must call this first, once, before doing any other // compiler/linker operations. // -int ShInitialize() + +void SetupBuiltinSymbolTable(int version, EProfile profile) { TInfoSink infoSink; - bool ret = true; - if (!InitProcess()) - return 0; + // This function is for lazy setup. See if already done. + int versionIndex = MapVersionToIndex(version); + if (SharedSymbolTables[versionIndex][profile][EShLangVertex]) + return; - // This method should be called once per process. If its called by multiple threads, then - // we need to have thread synchronization code around the initialization of per process - // global pool allocator - if (!PerProcessGPA) { - TPoolAllocator *builtInPoolAllocator = new TPoolAllocator(true); - builtInPoolAllocator->push(); - TPoolAllocator* gPoolAllocator = &GlobalPoolAllocator; - SetGlobalPoolAllocatorPtr(builtInPoolAllocator); + TPoolAllocator& savedGPA = GetGlobalPoolAllocator(); + TPoolAllocator *builtInPoolAllocator = new TPoolAllocator(true); + SetGlobalPoolAllocatorPtr(*builtInPoolAllocator); - TSymbolTable symTables[EShLangCount]; - GenerateBuiltInSymbolTable(0, infoSink, symTables); + TSymbolTable symTables[EShLangCount]; + GenerateBuiltInSymbolTable(infoSink, symTables, version, profile); - PerProcessGPA = new TPoolAllocator(true); - PerProcessGPA->push(); - SetGlobalPoolAllocatorPtr(PerProcessGPA); + SetGlobalPoolAllocatorPtr(*PerProcessGPA); - SymbolTables[EShLangVertex].copyTable(symTables[EShLangVertex]); - SymbolTables[EShLangFragment].copyTable(symTables[EShLangFragment]); + SharedSymbolTables[versionIndex][profile][EShLangVertex] = new TSymbolTable; + SharedSymbolTables[versionIndex][profile][EShLangVertex]->copyTable(symTables[EShLangVertex]); + SharedSymbolTables[versionIndex][profile][EShLangFragment] = new TSymbolTable; + SharedSymbolTables[versionIndex][profile][EShLangFragment]->copyTable(symTables[EShLangFragment]); + + symTables[EShLangVertex].pop(0); + symTables[EShLangFragment].pop(0); - SetGlobalPoolAllocatorPtr(gPoolAllocator); + builtInPoolAllocator->popAll(); + delete builtInPoolAllocator; - symTables[EShLangVertex].pop(0); - symTables[EShLangFragment].pop(0); + SetGlobalPoolAllocatorPtr(savedGPA); +} - builtInPoolAllocator->popAll(); - delete builtInPoolAllocator; +// returns true if something whas consumed +bool ConsumeWhitespaceComment(const char*& s) +{ + const char* startPoint = s; + + // first, skip white space + while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') { + ++s; } - return ret ? 1 : 0; + // then, check for a comment + if (*s == '/') { + if (*(s+1) == '/') { + s += 2; + do { + while (*s && *s != '\\' && *s != '\n') + ++s; + + if (*s == '\n' || *s == 0) { + if (*s == '\n') { + ++s; + if (*s == '\r') + ++s; + } // else it's 0, end of string + + // we reached the end of the comment + break; + } else { + // it's a '\', so we need to keep going, after skipping what's escaped + ++s; + if (*s == '\n') { + ++s; + if (*s == '\r') + ++s; + } else { + // skip the escaped character + if (*s) + ++s; + } + } + } while (true); + } else if (*(s+1) == '*') { + s += 2; + do { + while (*s && *s != '*') + ++s; + if (*s == '*') { + ++s; + if (*s == '/') { + ++s; + break; + } // else not end of comment, keep going + } else // end of string + break; + } while (true); + } // else it's not a comment + } // else it's not a comment + + return startPoint != s; +} + +void ScanVersion(const char* const shaderStrings[], int numStrings, int& version, EProfile& profile) +{ + // This function doesn't have to get all the semantics correct, + // just find the #version if there is a correct one present. + // The CPP will have the responsibility of getting all the semantics right. + + version = 0; // means not found + profile = ENoProfile; + + const char* s = &shaderStrings[0][0]; + + // TODO: ES error check: #version must be on first line + + while (ConsumeWhitespaceComment(s)) + ; + + // # + if (*s != '#') + return; + ++s; + + // whitespace + while (*s == ' ' || *s == '\t') { + ++s; + } + + // version + if (strncmp(s, "version", 7) != 0) + return; + + // whitespace + s += 7; + while (*s == ' ' || *s == '\t') { + ++s; + } + + // version number + while (*s >= '0' && *s <= '9') { + version = 10 * version + (*s - '0'); + ++s; + } + if (version == 0) + return; + + // whitespace + while (*s == ' ' || *s == '\t') { + ++s; + } + + // profile + const char* end = s; + while (*end != ' ' && *end != '\t' && *end != '\n') { + if (*end == 0) + return; + ++end; + } + int profileLength = end - s; + if (profileLength == 2 && strncmp(s, "es", profileLength) == 0) + profile = EEsProfile; + else if (profileLength == 4 && strncmp(s, "core", profileLength) == 0) + profile = ECoreProfile; + else if (profileLength == 13 && strncmp(s, "compatibility", profileLength) == 0) + profile = ECompatibilityProfile; +} + +bool DeduceProfile(TInfoSink& infoSink, int version, EProfile& profile) +{ + const int FirstProfileVersion = 150; + + if (profile == ENoProfile) { + if (version == 300) { + infoSink.info.message(EPrefixError, "#version: version 300 requires specifying the 'es' profile"); + profile = EEsProfile; + + return false; + } else if (version == 100) + profile = EEsProfile; + else if (version >= FirstProfileVersion) + profile = ECoreProfile; + else + profile = ENoProfile; + } else { + // a profile was provided... + if (version < 150) { + infoSink.info.message(EPrefixError, "#version: versions before 150 do not allow a profile token"); + if (version == 100) + profile = EEsProfile; + else + profile = ENoProfile; + + return false; + } else if (version == 300) { + if (profile != EEsProfile) { + infoSink.info.message(EPrefixError, "#version: version 300 supports only the es profile"); + + return false; + } + profile = EEsProfile; + } else { + if (profile == EEsProfile) { + infoSink.info.message(EPrefixError, "#version: only version 300 supports the es profile"); + if (version >= FirstProfileVersion) + profile = ECoreProfile; + else + profile = ENoProfile; + + return false; + } + // else: typical desktop case... e.g., "#version 410 core" + } + } + + return true; +} + + +}; // end anonymous namespace for local functions + +int ShInitialize() +{ + if (! InitProcess()) + return 0; + + // TODO: Thread safety: + // This method should be called once per process. If it's called by multiple threads, then + // we need to have thread synchronization code around the initialization of per process + // global pool allocator + if (! PerProcessGPA) { + PerProcessGPA = new TPoolAllocator(true); + } + + return true; } // @@ -156,88 +455,17 @@ void ShDestruct(ShHandle handle) // Cleanup symbol tables // int __fastcall ShFinalize() -{ - if (PerProcessGPA) { - PerProcessGPA->popAll(); - delete PerProcessGPA; - } - return 1; -} - -bool GenerateBuiltInSymbolTable(const TBuiltInResource* resources, TInfoSink& infoSink, TSymbolTable* symbolTables, EShLanguage language) { - TBuiltIns builtIns; - - if (resources) { - builtIns.initialize(*resources); - InitializeSymbolTable(builtIns.getBuiltInStrings(), language, infoSink, resources, symbolTables); - } else { - builtIns.initialize(); - InitializeSymbolTable(builtIns.getBuiltInStrings(), EShLangVertex, infoSink, resources, symbolTables); - InitializeSymbolTable(builtIns.getBuiltInStrings(), EShLangFragment, infoSink, resources, symbolTables); - } + for (int version = 0; version < VersionCount; ++version) + for (int p = 0; p < EProfileCount; ++p) + for (int lang = 0; lang < EShLangCount; ++lang) + delete SharedSymbolTables[version][p][lang]; - return true; -} - -bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, EShLanguage language, TInfoSink& infoSink, const TBuiltInResource* resources, TSymbolTable* symbolTables) -{ - TIntermediate intermediate(infoSink); - TSymbolTable* symbolTable; - - if (resources) - symbolTable = symbolTables; - else - symbolTable = &symbolTables[language]; - - TParseContext parseContext(*symbolTable, intermediate, language, infoSink, 110); - - GlobalParseContext = &parseContext; - - assert(symbolTable->isEmpty() || symbolTable->atSharedBuiltInLevel()); - - // - // Parse the built-ins. This should only happen once per - // language symbol table when no 'resources' are passed in. - // - // Push the symbol table to give it an initial scope. This - // push should not have a corresponding pop, so that built-ins - // are preserved, and the test for an empty table fails. - // - - symbolTable->push(); - - - //Initialize the Preprocessor - int ret = InitPreprocessor(); - if (ret) { - infoSink.info.message(EPrefixInternalError, "Unable to intialize the Preprocessor"); - return false; + if (PerProcessGPA) { + PerProcessGPA->popAll(); + delete PerProcessGPA; } - - ResetFlex(); - - for (TBuiltInStrings::iterator i = BuiltInStrings[parseContext.language].begin(); - i != BuiltInStrings[parseContext.language].end(); ++i) { - const char* builtInShaders[1]; - int builtInLengths[1]; - - builtInShaders[0] = (*i).c_str(); - builtInLengths[0] = (int) (*i).size(); - - if (PaParseStrings(const_cast(builtInShaders), builtInLengths, 1, parseContext) != 0) { - infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins"); - return false; - } - } - FinalizePreprocessor(); - - if (resources) { - IdentifyBuiltIns(parseContext.language, *symbolTable, *resources); - } else { - IdentifyBuiltIns(parseContext.language, *symbolTable); - } - return true; + return 1; } // @@ -262,12 +490,11 @@ int ShCompile( if (handle == 0) return 0; - TShHandleBase* base = reinterpret_cast(handle); TCompiler* compiler = base->getAsCompiler(); if (compiler == 0) return 0; - + GlobalPoolAllocator.push(); compiler->infoSink.info.erase(); compiler->infoSink.debug.erase(); @@ -275,14 +502,29 @@ int ShCompile( if (numStrings == 0) return 1; + int version; + EProfile profile; + ScanVersion(shaderStrings, numStrings, version, profile); + if (version == 0) + version = defaultVersion; + bool goodProfile = DeduceProfile(compiler->infoSink, version, profile); + TIntermediate intermediate(compiler->infoSink); - TSymbolTable symbolTable(SymbolTables[compiler->getLanguage()]); + + SetupBuiltinSymbolTable(version, profile); + TSymbolTable symbolTable(*SharedSymbolTables[MapVersionToIndex(version)] + [profile] + [compiler->getLanguage()]); // Add built-in symbols that are potentially context dependent; // they get popped again further down. - GenerateBuiltInSymbolTable(resources, compiler->infoSink, &symbolTable, compiler->getLanguage()); + AddContextSpecificSymbols(resources, compiler->infoSink, &symbolTable, version, profile, compiler->getLanguage()); + + TParseContext parseContext(symbolTable, intermediate, version, profile, compiler->getLanguage(), compiler->infoSink); + + if (! goodProfile) + parseContext.error(1, "incorrect", "#version", ""); - TParseContext parseContext(symbolTable, intermediate, compiler->getLanguage(), compiler->infoSink, defaultVersion); parseContext.initializeExtensionBehavior(); GlobalParseContext = &parseContext; @@ -298,7 +540,7 @@ int ShCompile( bool success = true; symbolTable.push(); - if (!symbolTable.atGlobalLevel()) + if (! symbolTable.atGlobalLevel()) parseContext.infoSink.info.message(EPrefixInternalError, "Wrong symbol table level"); if (parseContext.insertBuiltInArrayAtGlobalLevel()) @@ -326,7 +568,7 @@ int ShCompile( success = false; } } - } else if (!success) { + } else if (! success) { parseContext.infoSink.info.prefix(EPrefixError); parseContext.infoSink.info << parseContext.numErrors << " compilation errors. No code generated.\n\n"; success = false; @@ -579,4 +821,3 @@ int ShGetUniformLocation(const ShHandle handle, const char* name) return uniformMap->getLocation(name); } - diff --git a/glslang/MachineIndependent/glslang.l b/glslang/MachineIndependent/glslang.l index 8efe67770..360990738 100644 --- a/glslang/MachineIndependent/glslang.l +++ b/glslang/MachineIndependent/glslang.l @@ -479,14 +479,14 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon return 1; for (int i = 0; i < argc; ++i) { - if (!argv[i]) { + if (! argv[i]) { parseContextLocal.error(0, "Null shader source string", "", ""); parseContextLocal.recover(); return 1; } } - if (!strLen) { + if (! strLen) { argv0len = (int) strlen(argv[0]); strLen = &argv0len; } @@ -499,7 +499,16 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon cpp->notAVersionToken = 0; yylineno = 1; - if (*cpp->PaStrLen >= 0) { + // TODO: CPP: a shader containing nothing but white space and comments is valid, even though it has no parse tokens + int len = 0; + while (argv[0][len] == ' ' || + argv[0][len] == '\t' || + argv[0][len] == '\n' || + argv[0][len] == '\r') + if (++len >= strLen[0]) + return 0; + + if (*cpp->PaStrLen > 0) { int ret; #ifdef _WIN32 ret = yyparse(parseContextLocal); @@ -510,8 +519,7 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon return 1; else return 0; - } - else + } else return 0; } @@ -838,14 +846,18 @@ void ResetTString(void) void SetVersion(int version) { - TParseContext& pc = *((TParseContext *)cpp->pC); - pc.setVersion(version); + // called by the CPP, but this functionality is currently + // taken over by ScanVersion() before parsing starts + + // CPP should still report errors in semantics } void SetProfile(EProfile profile) { - TParseContext& pc = *((TParseContext *)cpp->pC); - pc.setProfile(profile); + // called by the CPP, but this functionality is currently + // taken over by ScanVersion() before parsing starts + + // CPP should still report errors in semantics } TBehavior GetBehavior(const char* behavior) diff --git a/glslang/MachineIndependent/preprocessor/cpp.c b/glslang/MachineIndependent/preprocessor/cpp.c index 927e91b00..b8fa1cbe6 100644 --- a/glslang/MachineIndependent/preprocessor/cpp.c +++ b/glslang/MachineIndependent/preprocessor/cpp.c @@ -78,6 +78,8 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // cpp.c // +// TODO: CPP handle escaped newlines in a // style comment, correctly done in ConsumeWhitespaceComment() + #define _CRT_SECURE_NO_WARNINGS #include