Commit 9d93a237 by Rex Xu

Implement 4 AMD-specific extensions.

- Support GL_AMD_shader_ballot (SPV_AMD_shader_ballot). - Support GL_AMD_shader_trinary_minmax (SPV_AMD_shader_trinary_minmax). - Support GL_AMD_shader_explicit_vertex_parameter (SPV_AMD_shader_explicit_vertex_parameter). - Support GL_AMD_gcn_shader (SPV_AMD_gcn_shader).
parent 934855a6
cmake_minimum_required(VERSION 2.8.12)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
option(ENABLE_AMD_EXTENSIONS "Enables support of AMD-specific extensions" OFF)
enable_testing()
set(CMAKE_INSTALL_PREFIX "install" CACHE STRING "prefix")
project(glslang)
if(ENABLE_AMD_EXTENSIONS)
add_definitions(-DAMD_EXTENSIONS)
endif(ENABLE_AMD_EXTENSIONS)
if(WIN32)
set(CMAKE_DEBUG_POSTFIX "d")
include(ChooseMSVCCRT.cmake)
......
......@@ -18,6 +18,11 @@ set(HEADERS
doc.h
disassemble.h)
if(ENABLE_AMD_EXTENSIONS)
set(HEADERS
GLSL.ext.AMD.h)
endif(ENABLE_AMD_EXTENSIONS)
add_library(SPIRV STATIC ${SOURCES} ${HEADERS})
set_property(TARGET SPIRV PROPERTY FOLDER glslang)
......
/*
** Copyright (c) 2014-2016 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and/or associated documentation files (the "Materials"),
** to deal in the Materials without restriction, including without limitation
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
** and/or sell copies of the Materials, and to permit persons to whom the
** Materials are furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Materials.
**
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
** IN THE MATERIALS.
*/
#ifndef GLSLextAMD_H
#define GLSLextAMD_H
enum BuiltIn;
enum Decoration;
enum Op;
static const int GLSLextAMDVersion = 100;
static const int GLSLextAMDRevision = 1;
// SPV_AMD_shader_ballot
static const char* const E_SPV_AMD_shader_ballot = "SPV_AMD_shader_ballot";
static const Op OpGroupIAddNonUniformAMD = static_cast<Op>(5000);
static const Op OpGroupFAddNonUniformAMD = static_cast<Op>(5001);
static const Op OpGroupFMinNonUniformAMD = static_cast<Op>(5002);
static const Op OpGroupUMinNonUniformAMD = static_cast<Op>(5003);
static const Op OpGroupSMinNonUniformAMD = static_cast<Op>(5004);
static const Op OpGroupFMaxNonUniformAMD = static_cast<Op>(5005);
static const Op OpGroupUMaxNonUniformAMD = static_cast<Op>(5006);
static const Op OpGroupSMaxNonUniformAMD = static_cast<Op>(5007);
enum ShaderBallotAMD {
ShaderBallotBadAMD = 0, // Don't use
SwizzleInvocationsAMD = 1,
SwizzleInvocationsMaskedAMD = 2,
WriteInvocationAMD = 3,
MbcntAMD = 4,
ShaderBallotCountAMD
};
// SPV_AMD_shader_trinary_minmax
static const char* const E_SPV_AMD_shader_trinary_minmax = "SPV_AMD_shader_trinary_minmax";
enum ShaderTrinaryMinMaxAMD {
ShaderTrinaryMinMaxBadAMD = 0, // Don't use
FMin3AMD = 1,
UMin3AMD = 2,
SMin3AMD = 3,
FMax3AMD = 4,
UMax3AMD = 5,
SMax3AMD = 6,
FMid3AMD = 7,
UMid3AMD = 8,
SMid3AMD = 9,
ShaderTrinaryMinMaxCountAMD
};
// SPV_AMD_shader_explicit_vertex_parameter
static const char* const E_SPV_AMD_shader_explicit_vertex_parameter = "SPV_AMD_shader_explicit_vertex_parameter";
static const BuiltIn BuiltInBaryCoordNoPerspAMD = static_cast<BuiltIn>(4992);
static const BuiltIn BuiltInBaryCoordNoPerspCentroidAMD = static_cast<BuiltIn>(4993);
static const BuiltIn BuiltInBaryCoordNoPerspSampleAMD = static_cast<BuiltIn>(4994);
static const BuiltIn BuiltInBaryCoordSmoothAMD = static_cast<BuiltIn>(4995);
static const BuiltIn BuiltInBaryCoordSmoothCentroidAMD = static_cast<BuiltIn>(4996);
static const BuiltIn BuiltInBaryCoordSmoothSampleAMD = static_cast<BuiltIn>(4997);
static const BuiltIn BuiltInBaryCoordPullModelAMD = static_cast<BuiltIn>(4998);
static const Decoration DecorationExplicitInterpAMD = static_cast<Decoration>(4999);
enum ShaderExplicitVertexParameterAMD {
ShaderExplicitVertexParameterBadAMD = 0, // Don't use
InterpolateAtVertexAMD = 1,
ShaderExplicitVertexParameterCountAMD
};
// SPV_AMD_gcn_shader
static const char* const E_SPV_AMD_gcn_shader = "SPV_AMD_gcn_shader";
enum GcnShaderAMD {
GcnShaderBadAMD = 0, // Don't use
CubeFaceIndexAMD = 1,
CubeFaceCoordAMD = 2,
TimeAMD = 3,
GcnShaderCountAMD
};
#endif // #ifndef GLSLextAMD_H
......@@ -2312,7 +2312,11 @@ void Builder::dump(std::vector<unsigned int>& out) const
capInst.dump(out);
}
// TBD: OpExtension ...
for (int e = 0; e < (int)extensions.size(); ++e) {
Instruction extInst(0, 0, OpExtension);
extInst.addStringOperand(extensions[e]);
extInst.dump(out);
}
dumpInstructions(out, imports);
Instruction memInst(0, 0, OpMemoryModel);
......@@ -2331,10 +2335,10 @@ void Builder::dump(std::vector<unsigned int>& out) const
sourceInst.addImmediateOperand(sourceVersion);
sourceInst.dump(out);
}
for (int e = 0; e < (int)extensions.size(); ++e) {
Instruction extInst(0, 0, OpSourceExtension);
extInst.addStringOperand(extensions[e]);
extInst.dump(out);
for (int e = 0; e < (int)sourceExtensions.size(); ++e) {
Instruction sourceExtInst(0, 0, OpSourceExtension);
sourceExtInst.addStringOperand(sourceExtensions[e]);
sourceExtInst.dump(out);
}
dumpInstructions(out, names);
dumpInstructions(out, lines);
......
......@@ -70,7 +70,8 @@ public:
source = lang;
sourceVersion = version;
}
void addSourceExtension(const char* ext) { extensions.push_back(ext); }
void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); }
void addExtensions(const char* ext) { extensions.push_back(ext); }
Id import(const char*);
void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem)
{
......@@ -552,6 +553,7 @@ public:
SourceLanguage source;
int sourceVersion;
std::vector<const char*> extensions;
std::vector<const char*> sourceExtensions;
AddressingModel addressModel;
MemoryModel memoryModel;
std::set<spv::Capability> capabilities;
......
......@@ -44,17 +44,26 @@
#include <sstream>
#include <cstring>
#include "disassemble.h"
#include "doc.h"
namespace spv {
// Include C-based headers that don't have a namespace
#include "GLSL.std.450.h"
extern "C" {
// Include C-based headers that don't have a namespace
#include "GLSL.std.450.h"
#ifdef AMD_EXTENSIONS
#include "GLSL.ext.AMD.h"
#endif
}
}
const char* GlslStd450DebugNames[spv::GLSLstd450Count];
#include "disassemble.h"
#include "doc.h"
namespace spv {
#ifdef AMD_EXTENSIONS
static const char* GLSLextAMDGetDebugNames(const char*, unsigned);
#endif
static void Kill(std::ostream& out, const char* message)
{
out << std::endl << "Disassembly failed: " << message << std::endl;
......@@ -64,6 +73,9 @@ static void Kill(std::ostream& out, const char* message)
// used to identify the extended instruction library imported when printing
enum ExtInstSet {
GLSL450Inst,
#ifdef AMD_EXTENSIONS
GLSLextAMDInst,
#endif
OpenCLExtInst,
};
......@@ -446,14 +458,26 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
--numOperands;
if (opCode == OpExtInst) {
ExtInstSet extInstSet = GLSL450Inst;
if (0 == memcmp("OpenCL", (const char*)(idDescriptor[stream[word-2]].c_str()), 6)) {
const char* name = idDescriptor[stream[word - 2]].c_str();
if (0 == memcmp("OpenCL", name, 6)) {
extInstSet = OpenCLExtInst;
#ifdef AMD_EXTENSIONS
} else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 ||
strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 ||
strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 ||
strcmp(spv::E_SPV_AMD_gcn_shader, name) == 0) {
extInstSet = GLSLextAMDInst;
#endif
}
unsigned entrypoint = stream[word - 1];
if (extInstSet == GLSL450Inst) {
if (entrypoint < GLSLstd450Count) {
out << "(" << GlslStd450DebugNames[entrypoint] << ")";
}
#ifdef AMD_EXTENSIONS
} else if (extInstSet == GLSLextAMDInst) {
out << "(" << GLSLextAMDGetDebugNames(name, entrypoint) << ")";
#endif
}
}
break;
......@@ -561,6 +585,50 @@ static void GLSLstd450GetDebugNames(const char** names)
names[GLSLstd450InterpolateAtOffset] = "InterpolateAtOffset";
}
#ifdef AMD_EXTENSIONS
static const char* GLSLextAMDGetDebugNames(const char* name, unsigned entrypoint)
{
if (strcmp(name, spv::E_SPV_AMD_shader_ballot) == 0) {
switch (entrypoint) {
case SwizzleInvocationsAMD: return "SwizzleInvocationsAMD";
case SwizzleInvocationsMaskedAMD: return "SwizzleInvocationsMaskedAMD";
case WriteInvocationAMD: return "WriteInvocationAMD";
case MbcntAMD: return "MbcntAMD";
default: return "Bad";
}
} else if (strcmp(name, spv::E_SPV_AMD_shader_trinary_minmax) == 0) {
switch (entrypoint) {
case FMin3AMD: return "FMin3AMD";
case UMin3AMD: return "UMin3AMD";
case SMin3AMD: return "SMin3AMD";
case FMax3AMD: return "FMax3AMD";
case UMax3AMD: return "UMax3AMD";
case SMax3AMD: return "SMax3AMD";
case FMid3AMD: return "FMid3AMD";
case UMid3AMD: return "UMid3AMD";
case SMid3AMD: return "SMid3AMD";
default: return "Bad";
}
} else if (strcmp(name, spv::E_SPV_AMD_shader_explicit_vertex_parameter) == 0) {
switch (entrypoint) {
case InterpolateAtVertexAMD: return "InterpolateAtVertexAMD";
default: return "Bad";
}
}
else if (strcmp(name, spv::E_SPV_AMD_gcn_shader) == 0) {
switch (entrypoint) {
case CubeFaceIndexAMD: return "CubeFaceIndexAMD";
case CubeFaceCoordAMD: return "CubeFaceCoordAMD";
case TimeAMD: return "TimeAMD";
default:
break;
}
}
return "Bad";
}
#endif
void Disassemble(std::ostream& out, const std::vector<unsigned int>& stream)
{
SpirvStream SpirvStream(out, stream);
......
......@@ -45,6 +45,15 @@
#include <string.h>
#include <algorithm>
#ifdef AMD_EXTENSIONS
namespace spv {
extern "C" {
// Include C-based headers that don't have a namespace
#include "GLSL.ext.AMD.h"
}
}
#endif
namespace spv {
//
......@@ -243,6 +252,10 @@ const char* DecorationString(int decoration)
case DecorationCeiling:
default: return "Bad";
#ifdef AMD_EXTENSIONS
case 4999: return "ExplicitInterpAMD";
#endif
}
}
......@@ -298,6 +311,16 @@ const char* BuiltInString(int builtIn)
case BuiltInCeiling:
default: return "Bad";
#ifdef AMD_EXTENSIONS
case 4992: return "BaryCoordNoPerspAMD";
case 4993: return "BaryCoordNoPerspCentroidAMD";
case 4994: return "BaryCoordNoPerspSampleAMD";
case 4995: return "BaryCoordSmoothAMD";
case 4996: return "BaryCoordSmoothCentroidAMD";
case 4997: return "BaryCoordSmoothSampleAMD";
case 4998: return "BaryCoordPullModelAMD";
#endif
}
}
......@@ -1107,12 +1130,27 @@ const char* OpcodeString(int op)
case OpcodeCeiling:
default:
return "Bad";
#ifdef AMD_EXTENSIONS
case 5000: return "OpGroupIAddNonUniformAMD";
case 5001: return "OpGroupFAddNonUniformAMD";
case 5002: return "OpGroupFMinNonUniformAMD";
case 5003: return "OpGroupUMinNonUniformAMD";
case 5004: return "OpGroupSMinNonUniformAMD";
case 5005: return "OpGroupFMaxNonUniformAMD";
case 5006: return "OpGroupUMaxNonUniformAMD";
case 5007: return "OpGroupSMaxNonUniformAMD";
#endif
}
}
// The set of objects that hold all the instruction/operand
// parameterization information.
#ifdef AMD_EXTENSIONS
InstructionParameters InstructionDesc[OpCodeMask + 1];
#else
InstructionParameters InstructionDesc[OpcodeCeiling];
#endif
OperandParameters ExecutionModeOperands[ExecutionModeCeiling];
OperandParameters DecorationOperands[DecorationCeiling];
......@@ -2703,6 +2741,48 @@ void Parameterize()
InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Num Events'");
InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Wait Events'");
InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Ret Event'");
#ifdef AMD_EXTENSIONS
InstructionDesc[OpGroupIAddNonUniformAMD].capabilities.push_back(CapabilityGroups);
InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandScope, "'Execution'");
InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandId, "'X'");
InstructionDesc[OpGroupFAddNonUniformAMD].capabilities.push_back(CapabilityGroups);
InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandScope, "'Execution'");
InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandId, "'X'");
InstructionDesc[OpGroupUMinNonUniformAMD].capabilities.push_back(CapabilityGroups);
InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandScope, "'Execution'");
InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandId, "'X'");
InstructionDesc[OpGroupSMinNonUniformAMD].capabilities.push_back(CapabilityGroups);
InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandScope, "'Execution'");
InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandId, "X");
InstructionDesc[OpGroupFMinNonUniformAMD].capabilities.push_back(CapabilityGroups);
InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandScope, "'Execution'");
InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandId, "X");
InstructionDesc[OpGroupUMaxNonUniformAMD].capabilities.push_back(CapabilityGroups);
InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandScope, "'Execution'");
InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandId, "X");
InstructionDesc[OpGroupSMaxNonUniformAMD].capabilities.push_back(CapabilityGroups);
InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandScope, "'Execution'");
InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandId, "X");
InstructionDesc[OpGroupFMaxNonUniformAMD].capabilities.push_back(CapabilityGroups);
InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandScope, "'Execution'");
InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandId, "X");
#endif
}
}; // end spv namespace
......@@ -186,6 +186,15 @@ enum TBuiltInVariable {
EbvSamplePosition,
EbvSampleMask,
EbvHelperInvocation,
#ifdef AMD_EXTENSIONS
EbvBaryCoordNoPersp,
EbvBaryCoordNoPerspCentroid,
EbvBaryCoordNoPerspSample,
EbvBaryCoordSmooth,
EbvBaryCoordSmoothCentroid,
EbvBaryCoordSmoothSample,
EbvBaryCoordPullModel,
#endif
EbvLast
};
......@@ -286,6 +295,15 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
case EbvSamplePosition: return "SamplePosition";
case EbvSampleMask: return "SampleMaskIn";
case EbvHelperInvocation: return "HelperInvocation";
#ifdef AMD_EXTENSIONS
case EbvBaryCoordNoPersp: return "BaryCoordNoPersp";
case EbvBaryCoordNoPerspCentroid: return "BaryCoordNoPerspCentroid";
case EbvBaryCoordNoPerspSample: return "BaryCoordNoPerspSample";
case EbvBaryCoordSmooth: return "BaryCoordSmooth";
case EbvBaryCoordSmoothCentroid: return "BaryCoordSmoothCentroid";
case EbvBaryCoordSmoothSample: return "BaryCoordSmoothSample";
case EbvBaryCoordPullModel: return "BaryCoordPullModel";
#endif
default: return "unknown built-in variable";
}
}
......
......@@ -405,6 +405,9 @@ public:
smooth = false;
flat = false;
nopersp = false;
#ifdef AMD_EXTENSIONS
explicitInterp = false;
#endif
patch = false;
sample = false;
coherent = false;
......@@ -438,6 +441,9 @@ public:
bool smooth : 1;
bool flat : 1;
bool nopersp : 1;
#ifdef AMD_EXTENSIONS
bool explicitInterp : 1;
#endif
bool patch : 1;
bool sample : 1;
bool coherent : 1;
......@@ -453,7 +459,11 @@ public:
}
bool isInterpolation() const
{
#ifdef AMD_EXTENSIONS
return flat || smooth || nopersp || explicitInterp;
#else
return flat || smooth || nopersp;
#endif
}
bool isAuxiliary() const
{
......@@ -1518,6 +1528,10 @@ public:
p += snprintf(p, end - p, "flat ");
if (qualifier.nopersp)
p += snprintf(p, end - p, "noperspective ");
#ifdef AMD_EXTENSIONS
if (qualifier.explicitInterp)
p += snprintf(p, end - p, "__explicitInterpAMD ");
#endif
if (qualifier.patch)
p += snprintf(p, end - p, "patch ");
if (qualifier.sample)
......
......@@ -246,6 +246,12 @@ enum TOperator {
EOpReflect,
EOpRefract,
#ifdef AMD_EXTENSIONS
EOpMin3,
EOpMax3,
EOpMid3,
#endif
EOpDPdx, // Fragment only
EOpDPdy, // Fragment only
EOpFwidth, // Fragment only
......@@ -260,6 +266,10 @@ enum TOperator {
EOpInterpolateAtSample, // Fragment only
EOpInterpolateAtOffset, // Fragment only
#ifdef AMD_EXTENSIONS
EOpInterpolateAtVertex,
#endif
EOpMatrixTimesMatrix,
EOpOuterProduct,
EOpDeterminant,
......@@ -291,6 +301,23 @@ enum TOperator {
EOpAllInvocations,
EOpAllInvocationsEqual,
#ifdef AMD_EXTENSIONS
EOpMinInvocations,
EOpMaxInvocations,
EOpAddInvocations,
EOpMinInvocationsNonUniform,
EOpMaxInvocationsNonUniform,
EOpAddInvocationsNonUniform,
EOpSwizzleInvocations,
EOpSwizzleInvocationsMasked,
EOpWriteInvocation,
EOpMbcnt,
EOpCubeFaceIndex,
EOpCubeFaceCoord,
EOpTime,
#endif
EOpAtomicAdd,
EOpAtomicMin,
EOpAtomicMax,
......
......@@ -2119,6 +2119,10 @@ void TParseContext::rValueErrorCheck(const TSourceLoc& loc, const char* op, TInt
TIntermSymbol* symNode = node->getAsSymbolNode();
if (symNode && symNode->getQualifier().writeonly)
error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str());
#ifdef AMD_EXTENSIONS
else if (symNode && symNode->getQualifier().explicitInterp)
error(loc, "can't read from explicitly-interpolated object: ", op, symNode->getName().c_str());
#endif
}
//
......@@ -2665,7 +2669,11 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali
publicType.basicType == EbtDouble)
profileRequires(loc, EEsProfile, 300, nullptr, "shader input/output");
if (! qualifier.flat) {
#ifdef AMD_EXTENSIONS
if (! qualifier.flat && ! qualifier.explicitInterp) {
#else
if (!qualifier.flat) {
#endif
if (publicType.basicType == EbtInt || publicType.basicType == EbtUint ||
publicType.basicType == EbtInt64 || publicType.basicType == EbtUint64 ||
publicType.basicType == EbtDouble ||
......@@ -2802,7 +2810,11 @@ void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, cons
// Multiple interpolation qualifiers (mostly done later by 'individual qualifiers')
if (src.isInterpolation() && dst.isInterpolation())
#ifdef AMD_EXTENSIONS
error(loc, "can only have one interpolation qualifier (flat, smooth, noperspective, __explicitInterpAMD)", "", "");
#else
error(loc, "can only have one interpolation qualifier (flat, smooth, noperspective)", "", "");
#endif
// Ordering
if (! force && ((profile != EEsProfile && version < 420) ||
......@@ -2858,6 +2870,9 @@ void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, cons
MERGE_SINGLETON(smooth);
MERGE_SINGLETON(flat);
MERGE_SINGLETON(nopersp);
#ifdef AMD_EXTENSIONS
MERGE_SINGLETON(explicitInterp);
#endif
MERGE_SINGLETON(patch);
MERGE_SINGLETON(sample);
MERGE_SINGLETON(coherent);
......
......@@ -553,6 +553,9 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["noperspective"] = NOPERSPECTIVE;
(*KeywordMap)["smooth"] = SMOOTH;
(*KeywordMap)["flat"] = FLAT;
#ifdef AMD_EXTENSIONS
(*KeywordMap)["__explicitInterpAMD"] = __EXPLICITINTERPAMD;
#endif
(*KeywordMap)["centroid"] = CENTROID;
(*KeywordMap)["precise"] = PRECISE;
(*KeywordMap)["invariant"] = INVARIANT;
......@@ -1117,6 +1120,14 @@ int TScanContext::tokenizeIdentifier()
return identifierOrType();
return keyword;
#ifdef AMD_EXTENSIONS
case __EXPLICITINTERPAMD:
if (parseContext.profile != EEsProfile && parseContext.version >= 450 &&
parseContext.extensionTurnedOn(E_GL_AMD_shader_explicit_vertex_parameter))
return keyword;
return identifierOrType();
#endif
case FLAT:
if (parseContext.profile == EEsProfile && parseContext.version < 300)
reservedWord();
......
......@@ -187,6 +187,13 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive] = EBhDisable;
extensionBehavior[E_GL_GOOGLE_include_directive] = EBhDisable;
#ifdef AMD_EXTENSIONS
extensionBehavior[E_GL_AMD_shader_ballot] = EBhDisable;
extensionBehavior[E_GL_AMD_shader_trinary_minmax] = EBhDisable;
extensionBehavior[E_GL_AMD_shader_explicit_vertex_parameter] = EBhDisable;
extensionBehavior[E_GL_AMD_gcn_shader] = EBhDisable;
#endif
// AEP
extensionBehavior[E_GL_ANDROID_extension_pack_es31a] = EBhDisable;
extensionBehavior[E_GL_KHR_blend_equation_advanced] = EBhDisable;
......@@ -286,6 +293,13 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_ARB_sparse_texture_clamp 1\n"
// "#define GL_ARB_cull_distance 1\n" // present for 4.5, but need extension control over block members
"#define GL_EXT_shader_non_constant_global_initializers 1\n"
#ifdef AMD_EXTENSIONS
"#define GL_AMD_shader_ballot 1\n"
"#define GL_AMD_shader_trinary_minmax 1\n"
"#define GL_AMD_shader_explicit_vertex_parameter 1\n"
"#define GL_AMD_gcn_shader 1\n"
#endif
;
}
......
......@@ -135,6 +135,13 @@ const char* const E_GL_EXT_shader_non_constant_global_initializers = "GL_EXT_sha
const char* const E_GL_GOOGLE_cpp_style_line_directive = "GL_GOOGLE_cpp_style_line_directive";
const char* const E_GL_GOOGLE_include_directive = "GL_GOOGLE_include_directive";
#ifdef AMD_EXTENSIONS
const char* const E_GL_AMD_shader_ballot = "GL_AMD_shader_ballot";
const char* const E_GL_AMD_shader_trinary_minmax = "GL_AMD_shader_trinary_minmax";
const char* const E_GL_AMD_shader_explicit_vertex_parameter = "GL_AMD_shader_explicit_vertex_parameter";
const char* const E_GL_AMD_gcn_shader = "GL_AMD_gcn_shader";
#endif
// AEP
const char* const E_GL_ANDROID_extension_pack_es31a = "GL_ANDROID_extension_pack_es31a";
const char* const E_GL_KHR_blend_equation_advanced = "GL_KHR_blend_equation_advanced";
......
......@@ -126,7 +126,7 @@ extern int yylex(YYSTYPE*, TParseContext&);
%token <lex> UNIFORM PATCH SAMPLE BUFFER SHARED
%token <lex> COHERENT VOLATILE RESTRICT READONLY WRITEONLY
%token <lex> DVEC2 DVEC3 DVEC4 DMAT2 DMAT3 DMAT4
%token <lex> NOPERSPECTIVE FLAT SMOOTH LAYOUT
%token <lex> NOPERSPECTIVE FLAT SMOOTH LAYOUT __EXPLICITINTERPAMD
%token <lex> MAT2X2 MAT2X3 MAT2X4
%token <lex> MAT3X2 MAT3X3 MAT3X4
......@@ -1050,6 +1050,15 @@ interpolation_qualifier
$$.init($1.loc);
$$.qualifier.nopersp = true;
}
| __EXPLICITINTERPAMD {
#ifdef AMD_EXTENSIONS
parseContext.globalCheck($1.loc, "__explicitInterpAMD");
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");
$$.init($1.loc);
$$.qualifier.explicitInterp = true;
#endif
}
;
layout_qualifier
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -355,6 +355,7 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
case EOpBallot: out.debug << "ballot"; break;
case EOpReadFirstInvocation: out.debug << "readFirstInvocation"; break;
case EOpAnyInvocation: out.debug << "anyInvocation"; break;
case EOpAllInvocations: out.debug << "allInvocations"; break;
case EOpAllInvocationsEqual: out.debug << "allInvocationsEqual"; break;
......@@ -365,6 +366,19 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
case EOpRcp: out.debug << "rcp"; break;
case EOpSaturate: out.debug << "saturate"; break;
#ifdef AMD_EXTENSIONS
case EOpMinInvocations: out.debug << "minInvocations"; break;
case EOpMaxInvocations: out.debug << "maxInvocations"; break;
case EOpAddInvocations: out.debug << "addInvocations"; break;
case EOpMinInvocationsNonUniform: out.debug << "minInvocationsNonUniform"; break;
case EOpMaxInvocationsNonUniform: out.debug << "maxInvocationsNonUniform"; break;
case EOpAddInvocationsNonUniform: out.debug << "addInvocationsNonUniform"; break;
case EOpMbcnt: out.debug << "mbcnt"; break;
case EOpCubeFaceIndex: out.debug << "cubeFaceIndex"; break;
case EOpCubeFaceCoord: out.debug << "cubeFaceCoord"; break;
#endif
default: out.debug.message(EPrefixError, "Bad unary op");
}
......@@ -482,6 +496,18 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpReadInvocation: out.debug << "readInvocation"; break;
#ifdef AMD_EXTENSIONS
case EOpSwizzleInvocations: out.debug << "swizzleInvocations"; break;
case EOpSwizzleInvocationsMasked: out.debug << "swizzleInvocationsMasked"; break;
case EOpWriteInvocation: out.debug << "writeInvocation"; break;
case EOpMin3: out.debug << "min3"; break;
case EOpMax3: out.debug << "max3"; break;
case EOpMid3: out.debug << "mid3"; break;
case EOpTime: out.debug << "time"; break;
#endif
case EOpAtomicAdd: out.debug << "AtomicAdd"; break;
case EOpAtomicMin: out.debug << "AtomicMin"; break;
case EOpAtomicMax: out.debug << "AtomicMax"; break;
......@@ -539,6 +565,9 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpInterpolateAtSample: out.debug << "interpolateAtSample"; break;
case EOpInterpolateAtOffset: out.debug << "interpolateAtOffset"; break;
#ifdef AMD_EXTENSIONS
case EOpInterpolateAtVertex: out.debug << "interpolateAtVertex"; break;
#endif
case EOpSinCos: out.debug << "sincos"; break;
case EOpGenMul: out.debug << "mul"; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment