- glslang compiler and Vulkan backend update.

This commit is contained in:
Christoph Oelckers 2022-07-02 10:09:59 +02:00
parent 0c03d3e364
commit 2c3fcbaf51
127 changed files with 25652 additions and 11531 deletions

View file

@ -13,18 +13,14 @@ endif(WIN32)
if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
add_compile_options(-Wall -Wmaybe-uninitialized -Wuninitialized -Wunused -Wunused-local-typedefs
-Wno-unused-parameter -Wunused-value -Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable -fno-exceptions)
-Wunused-parameter -Wunused-value -Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable -fno-exceptions)
add_compile_options(-Wno-reorder) # disable this from -Wall, since it happens all over.
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
add_compile_options(-Wall -Wuninitialized -Wunused -Wunused-local-typedefs
-Wno-unused-parameter -Wunused-value -Wunused-variable)
-Wunused-parameter -Wunused-value -Wunused-variable)
add_compile_options(-Wno-reorder) # disable this from -Wall, since it happens all over.
endif()
if (MSVC)
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4146" )
endif()
# Request C++11
if(${CMAKE_VERSION} VERSION_LESS 3.1)
# CMake versions before 3.1 do not understand CMAKE_CXX_STANDARD
@ -52,6 +48,7 @@ set(SOURCES
MachineIndependent/RemoveTree.cpp
MachineIndependent/Scan.cpp
MachineIndependent/ShaderLang.cpp
MachineIndependent/SpirvIntrinsics.cpp
MachineIndependent/SymbolTable.cpp
MachineIndependent/Versions.cpp
MachineIndependent/intermOut.cpp
@ -79,8 +76,8 @@ set(HEADERS
Include/intermediate.h
Include/PoolAlloc.h
Include/ResourceLimits.h
Include/revision.h
Include/ShHandle.h
Include/SpirvIntrinsics.h
Include/Types.h
MachineIndependent/attribute.h
MachineIndependent/glslang_tab.cpp.h

View file

@ -2,6 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@ -61,8 +62,13 @@ enum TBasicType {
EbtSampler,
EbtStruct,
EbtBlock,
EbtAccStructNV,
EbtAccStruct,
EbtReference,
EbtRayQuery,
#ifndef GLSLANG_WEB
// SPIR-V type defined by spirv_type
EbtSpirvType,
#endif
// HLSL types that live only temporarily.
EbtString,
@ -89,12 +95,15 @@ enum TStorageQualifier {
EvqUniform, // read only, shared with app
EvqBuffer, // read/write, shared with app
EvqShared, // compute shader's read/write 'shared' qualifier
#ifndef GLSLANG_WEB
EvqSpirvStorageClass, // spirv_storage_class
#endif
EvqPayloadNV,
EvqPayloadInNV,
EvqHitAttrNV,
EvqCallableDataNV,
EvqCallableDataInNV,
EvqPayload,
EvqPayloadIn,
EvqHitAttr,
EvqCallableData,
EvqCallableDataIn,
// parameters
EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter
@ -226,9 +235,15 @@ enum TBuiltInVariable {
EbvViewIndex,
EbvDeviceIndex,
EbvShadingRateKHR,
EbvPrimitiveShadingRateKHR,
EbvFragSizeEXT,
EbvFragInvocationCountEXT,
EbvSecondaryFragDataEXT,
EbvSecondaryFragColorEXT,
EbvViewportMaskNV,
EbvSecondaryPositionNV,
EbvSecondaryViewportMaskNV,
@ -238,23 +253,30 @@ enum TBuiltInVariable {
EbvFragmentSizeNV,
EbvInvocationsPerPixelNV,
// ray tracing
EbvLaunchIdNV,
EbvLaunchSizeNV,
EbvInstanceCustomIndexNV,
EbvWorldRayOriginNV,
EbvWorldRayDirectionNV,
EbvObjectRayOriginNV,
EbvObjectRayDirectionNV,
EbvRayTminNV,
EbvRayTmaxNV,
EbvHitTNV,
EbvHitKindNV,
EbvObjectToWorldNV,
EbvWorldToObjectNV,
EbvIncomingRayFlagsNV,
EbvLaunchId,
EbvLaunchSize,
EbvInstanceCustomIndex,
EbvGeometryIndex,
EbvWorldRayOrigin,
EbvWorldRayDirection,
EbvObjectRayOrigin,
EbvObjectRayDirection,
EbvRayTmin,
EbvRayTmax,
EbvCullMask,
EbvHitT,
EbvHitKind,
EbvObjectToWorld,
EbvObjectToWorld3x4,
EbvWorldToObject,
EbvWorldToObject3x4,
EbvIncomingRayFlags,
EbvCurrentRayTimeNV,
// barycentrics
EbvBaryCoordNV,
EbvBaryCoordNoPerspNV,
EbvBaryCoordEXT,
EbvBaryCoordNoPerspEXT,
// mesh shaders
EbvTaskCountNV,
EbvPrimitiveCountNV,
@ -310,6 +332,9 @@ __inline const char* GetStorageQualifierString(TStorageQualifier q)
case EvqGlobal: return "global"; break;
case EvqConst: return "const"; break;
case EvqConstReadOnly: return "const (read only)"; break;
#ifndef GLSLANG_WEB
case EvqSpirvStorageClass: return "spirv_storage_class"; break;
#endif
case EvqVaryingIn: return "in"; break;
case EvqVaryingOut: return "out"; break;
case EvqUniform: return "uniform"; break;
@ -328,11 +353,11 @@ __inline const char* GetStorageQualifierString(TStorageQualifier q)
case EvqPointCoord: return "gl_PointCoord"; break;
case EvqFragColor: return "fragColor"; break;
case EvqFragDepth: return "gl_FragDepth"; break;
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;
case EvqPayload: return "rayPayloadNV"; break;
case EvqPayloadIn: return "rayPayloadInNV"; break;
case EvqHitAttr: return "hitAttributeNV"; break;
case EvqCallableData: return "callableDataNV"; break;
case EvqCallableDataIn: return "callableDataInNV"; break;
default: return "unknown qualifier";
}
}
@ -428,6 +453,9 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
case EbvFragSizeEXT: return "FragSizeEXT";
case EbvFragInvocationCountEXT: return "FragInvocationCountEXT";
case EbvSecondaryFragDataEXT: return "SecondaryFragDataEXT";
case EbvSecondaryFragColorEXT: return "SecondaryFragColorEXT";
case EbvViewportMaskNV: return "ViewportMaskNV";
case EbvSecondaryPositionNV: return "SecondaryPositionNV";
case EbvSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
@ -436,23 +464,27 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
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 EbvLaunchId: return "LaunchIdNV";
case EbvLaunchSize: return "LaunchSizeNV";
case EbvInstanceCustomIndex: return "InstanceCustomIndexNV";
case EbvGeometryIndex: return "GeometryIndexEXT";
case EbvWorldRayOrigin: return "WorldRayOriginNV";
case EbvWorldRayDirection: return "WorldRayDirectionNV";
case EbvObjectRayOrigin: return "ObjectRayOriginNV";
case EbvObjectRayDirection: return "ObjectRayDirectionNV";
case EbvRayTmin: return "ObjectRayTminNV";
case EbvRayTmax: return "ObjectRayTmaxNV";
case EbvHitT: return "HitTNV";
case EbvHitKind: return "HitKindNV";
case EbvIncomingRayFlags: return "IncomingRayFlagsNV";
case EbvObjectToWorld: return "ObjectToWorldNV";
case EbvWorldToObject: return "WorldToObjectNV";
case EbvCurrentRayTimeNV: return "CurrentRayTimeNV";
case EbvBaryCoordNV: return "BaryCoordNV";
case EbvBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";
case EbvBaryCoordEXT:
case EbvBaryCoordNV: return "BaryCoordKHR";
case EbvBaryCoordNoPerspEXT:
case EbvBaryCoordNoPerspNV: return "BaryCoordNoPerspKHR";
case EbvTaskCountNV: return "TaskCountNV";
case EbvPrimitiveCountNV: return "PrimitiveCountNV";
@ -468,6 +500,9 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
case EbvWarpID: return "WarpIDNV";
case EbvSMID: return "SMIDNV";
case EbvShadingRateKHR: return "ShadingRateKHR";
case EbvPrimitiveShadingRateKHR: return "PrimitiveShadingRateKHR";
default: return "unknown built-in variable";
}
}

View file

@ -37,6 +37,22 @@
#ifndef _COMMON_INCLUDED_
#define _COMMON_INCLUDED_
#include <algorithm>
#include <cassert>
#ifdef _MSC_VER
#include <cfloat>
#else
#include <cmath>
#endif
#include <cstdio>
#include <cstdlib>
#include <list>
#include <map>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#if defined(__ANDROID__) || (defined(_MSC_VER) && _MSC_VER < 1700)
#include <sstream>
@ -50,7 +66,7 @@ std::string to_string(const T& val) {
}
#endif
#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) || defined MINGW_HAS_SECURE_API
#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) || MINGW_HAS_SECURE_API
#include <basetsd.h>
#ifndef snprintf
#define snprintf sprintf_s
@ -94,18 +110,6 @@ std::string to_string(const T& val) {
#pragma warning(disable : 4201) // nameless union
#endif
#include <set>
#include <unordered_set>
#include <vector>
#include <map>
#include <unordered_map>
#include <list>
#include <algorithm>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include "PoolAlloc.h"
//
@ -196,6 +200,10 @@ template <class K, class D, class HASH = std::hash<K>, class PRED = std::equal_t
class TUnorderedMap : public std::unordered_map<K, D, HASH, PRED, pool_allocator<std::pair<K const, D> > > {
};
template <class K, class CMP = std::less<K> >
class TSet : public std::set<K, CMP, pool_allocator<K> > {
};
//
// Persistent string memory. Should only be used for strings that survive
// across compiles/links.
@ -211,7 +219,7 @@ template <class T> T Max(const T a, const T b) { return a > b ? a : b; }
//
// Create a TString object from an integer.
//
#if defined _MSC_VER || defined MINGW_HAS_SECURE_API
#if defined _MSC_VER || MINGW_HAS_SECURE_API
inline const TString String(const int i, const int base = 10)
{
char text[16]; // 32 bit ints are at most 10 digits in base 10
@ -288,6 +296,46 @@ template <class T> bool IsMultipleOfPow2(T number, int powerOf2)
return ! (number & (powerOf2 - 1));
}
// Returns log2 of an integer power of 2.
// T should be integral.
template <class T> int IntLog2(T n)
{
assert(IsPow2(n));
int result = 0;
while ((T(1) << result) != n) {
result++;
}
return result;
}
inline bool IsInfinity(double x) {
#ifdef _MSC_VER
switch (_fpclass(x)) {
case _FPCLASS_NINF:
case _FPCLASS_PINF:
return true;
default:
return false;
}
#else
return std::isinf(x);
#endif
}
inline bool IsNan(double x) {
#ifdef _MSC_VER
switch (_fpclass(x)) {
case _FPCLASS_SNAN:
case _FPCLASS_QNAN:
return true;
default:
return false;
}
#else
return std::isnan(x);
#endif
}
} // end namespace glslang
#endif // _COMMON_INCLUDED_

View file

@ -921,7 +921,7 @@ public:
else
unionArray = new TConstUnionVector(size);
}
TConstUnionArray(const TConstUnionArray& a) : unionArray(a.unionArray) { }
TConstUnionArray(const TConstUnionArray& a) = default;
TConstUnionArray(const TConstUnionArray& a, int start, int size)
{
unionArray = new TConstUnionVector(size);

View file

@ -306,6 +306,8 @@ public:
TPoolAllocator& getAllocator() const { return allocator; }
pool_allocator select_on_container_copy_construction() const { return pool_allocator{}; }
protected:
pool_allocator& operator=(const pool_allocator&) { return *this; }
TPoolAllocator& allocator;

View file

@ -142,6 +142,7 @@ struct TBuiltInResource {
int maxTaskWorkGroupSizeY_NV;
int maxTaskWorkGroupSizeZ_NV;
int maxMeshViewCountNV;
int maxDualSourceDrawBuffersEXT;
TLimits limits;
};

View file

@ -0,0 +1,128 @@
//
// Copyright(C) 2021 Advanced Micro Devices, 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.
//
#pragma once
#ifndef GLSLANG_WEB
//
// GL_EXT_spirv_intrinsics
//
#include "Common.h"
namespace glslang {
class TIntermTyped;
class TIntermConstantUnion;
class TType;
// SPIR-V requirements
struct TSpirvRequirement {
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
// capability = [..]
TSet<TString> extensions;
// extension = [..]
TSet<int> capabilities;
};
// SPIR-V execution modes
struct TSpirvExecutionMode {
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
// spirv_execution_mode
TMap<int, TVector<const TIntermConstantUnion*>> modes;
// spirv_execution_mode_id
TMap<int, TVector<const TIntermTyped*> > modeIds;
};
// SPIR-V decorations
struct TSpirvDecorate {
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
// spirv_decorate
TMap<int, TVector<const TIntermConstantUnion*> > decorates;
// spirv_decorate_id
TMap<int, TVector<const TIntermTyped*>> decorateIds;
// spirv_decorate_string
TMap<int, TVector<const TIntermConstantUnion*> > decorateStrings;
};
// SPIR-V instruction
struct TSpirvInstruction {
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
TSpirvInstruction() { set = ""; id = -1; }
bool operator==(const TSpirvInstruction& rhs) const { return set == rhs.set && id == rhs.id; }
bool operator!=(const TSpirvInstruction& rhs) const { return !operator==(rhs); }
// spirv_instruction
TString set;
int id;
};
// SPIR-V type parameter
struct TSpirvTypeParameter {
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
TSpirvTypeParameter(const TIntermConstantUnion* arg) { constant = arg; }
bool operator==(const TSpirvTypeParameter& rhs) const { return constant == rhs.constant; }
bool operator!=(const TSpirvTypeParameter& rhs) const { return !operator==(rhs); }
const TIntermConstantUnion* constant;
};
typedef TVector<TSpirvTypeParameter> TSpirvTypeParameters;
// SPIR-V type
struct TSpirvType {
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
bool operator==(const TSpirvType& rhs) const
{
return spirvInst == rhs.spirvInst && typeParams == rhs.typeParams;
}
bool operator!=(const TSpirvType& rhs) const { return !operator==(rhs); }
// spirv_type
TSpirvInstruction spirvInst;
TSpirvTypeParameters typeParams;
};
} // end namespace glslang
#endif // GLSLANG_WEB

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,62 @@
// Copyright (C) 2020 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 The Khronos Group Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#ifndef GLSLANG_BUILD_INFO
#define GLSLANG_BUILD_INFO
#define GLSLANG_VERSION_MAJOR 11
#define GLSLANG_VERSION_MINOR 10
#define GLSLANG_VERSION_PATCH 0
#define GLSLANG_VERSION_FLAVOR ""
#define GLSLANG_VERSION_GREATER_THAN(major, minor, patch) \
(((major) > GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \
(((minor) > GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \
((patch) > GLSLANG_VERSION_PATCH)))))
#define GLSLANG_VERSION_GREATER_OR_EQUAL_TO(major, minor, patch) \
(((major) > GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \
(((minor) > GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \
((patch) >= GLSLANG_VERSION_PATCH)))))
#define GLSLANG_VERSION_LESS_THAN(major, minor, patch) \
(((major) < GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \
(((minor) < GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \
((patch) < GLSLANG_VERSION_PATCH)))))
#define GLSLANG_VERSION_LESS_OR_EQUAL_TO(major, minor, patch) \
(((major) < GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \
(((minor) < GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \
((patch) <= GLSLANG_VERSION_PATCH)))))
#endif // GLSLANG_BUILD_INFO

View file

@ -2,6 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2016 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@ -70,6 +71,9 @@ enum TOperator {
EOpFunctionCall,
EOpFunction, // For function definition
EOpParameters, // an aggregate listing the parameters to a function
#ifndef GLSLANG_WEB
EOpSpirvInst,
#endif
//
// Unary operators
@ -279,6 +283,12 @@ enum TOperator {
EOpConvUvec2ToPtr,
EOpConvPtrToUvec2,
// uint64_t -> accelerationStructureEXT
EOpConvUint64ToAccStruct,
// uvec2 -> accelerationStructureEXT
EOpConvUvec2ToAccStruct,
//
// binary operations
//
@ -586,6 +596,7 @@ enum TOperator {
EOpTime,
EOpAtomicAdd,
EOpAtomicSubtract,
EOpAtomicMin,
EOpAtomicMax,
EOpAtomicAnd,
@ -621,17 +632,22 @@ enum TOperator {
EOpIsHelperInvocation,
EOpDebugPrintf,
//
// Branch
//
EOpKill, // Fragment only
EOpKill, // Fragment only
EOpTerminateInvocation, // Fragment only
EOpDemote, // Fragment only
EOpTerminateRayKHR, // Any-hit only
EOpIgnoreIntersectionKHR, // Any-hit only
EOpReturn,
EOpBreak,
EOpContinue,
EOpCase,
EOpDefault,
EOpDemote, // Fragment only
//
// Constructors
@ -748,6 +764,7 @@ enum TOperator {
EOpConstructNonuniform, // expected to be transformed away, not present in final AST
EOpConstructReference,
EOpConstructCooperativeMatrix,
EOpConstructAccStruct,
EOpConstructGuardEnd,
//
@ -909,11 +926,43 @@ enum TOperator {
EOpMul32x16,
EOpTraceNV,
EOpReportIntersectionNV,
EOpTraceRayMotionNV,
EOpTraceKHR,
EOpReportIntersection,
EOpIgnoreIntersectionNV,
EOpTerminateRayNV,
EOpExecuteCallableNV,
EOpExecuteCallableKHR,
EOpWritePackedPrimitiveIndices4x8NV,
//
// GL_EXT_ray_query operations
//
EOpRayQueryInitialize,
EOpRayQueryTerminate,
EOpRayQueryGenerateIntersection,
EOpRayQueryConfirmIntersection,
EOpRayQueryProceed,
EOpRayQueryGetIntersectionType,
EOpRayQueryGetRayTMin,
EOpRayQueryGetRayFlags,
EOpRayQueryGetIntersectionT,
EOpRayQueryGetIntersectionInstanceCustomIndex,
EOpRayQueryGetIntersectionInstanceId,
EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset,
EOpRayQueryGetIntersectionGeometryIndex,
EOpRayQueryGetIntersectionPrimitiveIndex,
EOpRayQueryGetIntersectionBarycentrics,
EOpRayQueryGetIntersectionFrontFace,
EOpRayQueryGetIntersectionCandidateAABBOpaque,
EOpRayQueryGetIntersectionObjectRayDirection,
EOpRayQueryGetIntersectionObjectRayOrigin,
EOpRayQueryGetWorldRayDirection,
EOpRayQueryGetWorldRayOrigin,
EOpRayQueryGetIntersectionObjectToWorld,
EOpRayQueryGetIntersectionWorldToObject,
//
// HLSL operations
//
@ -1091,6 +1140,8 @@ public:
virtual TBasicType getBasicType() const { return type.getBasicType(); }
virtual TQualifier& getQualifier() { return type.getQualifier(); }
virtual const TQualifier& getQualifier() const { return type.getQualifier(); }
virtual TArraySizes* getArraySizes() { return type.getArraySizes(); }
virtual const TArraySizes* getArraySizes() const { return type.getArraySizes(); }
virtual void propagatePrecision(TPrecisionQualifier);
virtual int getVectorSize() const { return type.getVectorSize(); }
virtual int getMatrixCols() const { return type.getMatrixCols(); }
@ -1104,7 +1155,7 @@ public:
virtual bool isIntegerDomain() const { return type.isIntegerDomain(); }
bool isAtomic() const { return type.isAtomic(); }
bool isReference() const { return type.isReference(); }
TString getCompleteString() const { return type.getCompleteString(); }
TString getCompleteString(bool enhanced = false) const { return type.getCompleteString(enhanced); }
protected:
TIntermTyped& operator=(const TIntermTyped&);
@ -1199,6 +1250,7 @@ public:
TOperator getFlowOp() const { return flowOp; }
TIntermTyped* getExpression() const { return expression; }
void setExpression(TIntermTyped* pExpression) { expression = pExpression; }
void updatePrecision(TPrecisionQualifier parentPrecision);
protected:
TOperator flowOp;
TIntermTyped* expression;
@ -1230,15 +1282,15 @@ public:
// if symbol is initialized as symbol(sym), the memory comes from the pool allocator of sym. If sym comes from
// per process threadPoolAllocator, then it causes increased memory usage per compile
// it is essential to use "symbol = sym" to assign to symbol
TIntermSymbol(int i, const TString& n, const TType& t)
TIntermSymbol(long long i, const TString& n, const TType& t)
: TIntermTyped(t), id(i),
#ifndef GLSLANG_WEB
flattenSubset(-1),
#endif
constSubtree(nullptr)
{ name = n; }
virtual int getId() const { return id; }
virtual void changeId(int i) { id = i; }
virtual long long getId() const { return id; }
virtual void changeId(long long i) { id = i; }
virtual const TString& getName() const { return name; }
virtual void traverse(TIntermTraverser*);
virtual TIntermSymbol* getAsSymbolNode() { return this; }
@ -1249,15 +1301,17 @@ public:
TIntermTyped* getConstSubtree() const { return constSubtree; }
#ifndef GLSLANG_WEB
void setFlattenSubset(int subset) { flattenSubset = subset; }
virtual const TString& getAccessName() const;
int getFlattenSubset() const { return flattenSubset; } // -1 means full object
#endif
// This is meant for cases where a node has already been constructed, and
// later on, it becomes necessary to switch to a different symbol.
virtual void switchId(int newId) { id = newId; }
virtual void switchId(long long newId) { id = newId; }
protected:
int id; // the unique id of the symbol this node represents
long long id; // the unique id of the symbol this node represents
#ifndef GLSLANG_WEB
int flattenSubset; // how deeply the flattened object rooted at id has been dereferenced
#endif
@ -1566,8 +1620,15 @@ public:
virtual TIntermUnary* getAsUnaryNode() { return this; }
virtual const TIntermUnary* getAsUnaryNode() const { return this; }
virtual void updatePrecision();
#ifndef GLSLANG_WEB
void setSpirvInstruction(const TSpirvInstruction& inst) { spirvInst = inst; }
const TSpirvInstruction& getSpirvInstruction() const { return spirvInst; }
#endif
protected:
TIntermTyped* operand;
#ifndef GLSLANG_WEB
TSpirvInstruction spirvInst;
#endif
};
typedef TVector<TIntermNode*> TIntermSequence;
@ -1582,6 +1643,7 @@ public:
~TIntermAggregate() { delete pragmaTable; }
virtual TIntermAggregate* getAsAggregate() { return this; }
virtual const TIntermAggregate* getAsAggregate() const { return this; }
virtual void updatePrecision();
virtual void setOperator(TOperator o) { op = o; }
virtual TIntermSequence& getSequence() { return sequence; }
virtual const TIntermSequence& getSequence() const { return sequence; }
@ -1598,6 +1660,10 @@ public:
bool getDebug() const { return debug; }
void setPragmaTable(const TPragmaTable& pTable);
const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
#ifndef GLSLANG_WEB
void setSpirvInstruction(const TSpirvInstruction& inst) { spirvInst = inst; }
const TSpirvInstruction& getSpirvInstruction() const { return spirvInst; }
#endif
protected:
TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
@ -1608,6 +1674,9 @@ protected:
bool optimize;
bool debug;
TPragmaTable* pragmaTable;
#ifndef GLSLANG_WEB
TSpirvInstruction spirvInst;
#endif
};
//
@ -1625,8 +1694,11 @@ public:
flatten(false), dontFlatten(false) {}
virtual void traverse(TIntermTraverser*);
virtual TIntermTyped* getCondition() const { return condition; }
virtual void setCondition(TIntermTyped* c) { condition = c; }
virtual TIntermNode* getTrueBlock() const { return trueBlock; }
virtual void setTrueBlock(TIntermTyped* tb) { trueBlock = tb; }
virtual TIntermNode* getFalseBlock() const { return falseBlock; }
virtual void setFalseBlock(TIntermTyped* fb) { falseBlock = fb; }
virtual TIntermSelection* getAsSelectionNode() { return this; }
virtual const TIntermSelection* getAsSelectionNode() const { return this; }

View file

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

View file

@ -1,13 +0,0 @@
// The file revision.h should be updated to the latest version, somehow, on
// check-in, if glslang has changed.
//
// revision.template is the source for revision.h when using SubWCRev as the
// method of updating revision.h. You don't have to do it this way, the
// requirement is only that revision.h gets updated.
//
// revision.h is under source control so that not all consumers of glslang
// source have to figure out how to create revision.h just to get a build
// going. However, if it is not updated, it can be a version behind.
#define GLSLANG_REVISION "$WCREV$"
#define GLSLANG_DATE "$WCDATE$"

View file

@ -2,7 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Copyright (C) 2018 Google, Inc.
// Copyright (C) 2018-2020 Google, Inc.
//
// All rights reserved.
//
@ -42,39 +42,14 @@
#include <cstdlib>
#include <climits>
#ifdef _MSC_VER
#pragma warning(disable: 4146) // warning C4146: unary minus operator applied to unsigned type, result still unsigned
#endif
namespace {
using namespace glslang;
typedef union {
double d;
int i[2];
} DoubleIntUnion;
// Some helper functions
bool isNan(double x)
{
DoubleIntUnion u;
// tough to find a platform independent library function, do it directly
u.d = x;
int bitPatternL = u.i[0];
int bitPatternH = u.i[1];
return (bitPatternH & 0x7ff80000) == 0x7ff80000 &&
((bitPatternH & 0xFFFFF) != 0 || bitPatternL != 0);
}
bool isInf(double x)
{
DoubleIntUnion u;
// tough to find a platform independent library function, do it directly
u.d = x;
int bitPatternL = u.i[0];
int bitPatternH = u.i[1];
return (bitPatternH & 0x7ff00000) == 0x7ff00000 &&
(bitPatternH & 0xFFFFF) == 0 && bitPatternL == 0;
}
const double pi = 3.1415926535897932384626433832795;
} // end anonymous namespace
@ -529,7 +504,12 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
case EbtDouble:
case EbtFloat16:
case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break;
case EbtInt: newConstArray[i].setIConst(-unionArray[i].getIConst()); break;
// Note: avoid UBSAN error regarding negating 0x80000000
case EbtInt: newConstArray[i].setIConst(
static_cast<unsigned int>(unionArray[i].getIConst()) == 0x80000000
? -0x7FFFFFFF - 1
: -unionArray[i].getIConst());
break;
case EbtUint: newConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst()))); break;
#ifndef GLSLANG_WEB
case EbtInt8: newConstArray[i].setI8Const(-unionArray[i].getI8Const()); break;
@ -599,17 +579,11 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
newConstArray[i].setDConst(log(unionArray[i].getDConst()));
break;
case EOpExp2:
{
const double inv_log2_e = 0.69314718055994530941723212145818;
newConstArray[i].setDConst(exp(unionArray[i].getDConst() * inv_log2_e));
break;
}
newConstArray[i].setDConst(exp2(unionArray[i].getDConst()));
break;
case EOpLog2:
{
const double log2_e = 1.4426950408889634073599246810019;
newConstArray[i].setDConst(log2_e * log(unionArray[i].getDConst()));
break;
}
newConstArray[i].setDConst(log2(unionArray[i].getDConst()));
break;
case EOpSqrt:
newConstArray[i].setDConst(sqrt(unionArray[i].getDConst()));
break;
@ -664,12 +638,12 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
case EOpIsNan:
{
newConstArray[i].setBConst(isNan(unionArray[i].getDConst()));
newConstArray[i].setBConst(IsNan(unionArray[i].getDConst()));
break;
}
case EOpIsInf:
{
newConstArray[i].setBConst(isInf(unionArray[i].getDConst()));
newConstArray[i].setBConst(IsInfinity(unionArray[i].getDConst()));
break;
}
@ -1012,6 +986,7 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
case EOpMin:
case EOpMax:
case EOpMix:
case EOpMod:
case EOpClamp:
case EOpLessThan:
case EOpGreaterThan:
@ -1074,6 +1049,14 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
case EOpPow:
newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
break;
case EOpMod:
{
double arg0 = childConstUnions[0][arg0comp].getDConst();
double arg1 = childConstUnions[1][arg1comp].getDConst();
double result = arg0 - arg1 * floor(arg0 / arg1);
newConstArray[comp].setDConst(result);
break;
}
case EOpMin:
switch(children[0]->getAsTyped()->getBasicType()) {
case EbtFloat16:

File diff suppressed because it is too large Load diff

View file

@ -71,6 +71,13 @@ void TIntermConstantUnion::traverse(TIntermTraverser *it)
it->visitConstantUnion(this);
}
const TString& TIntermSymbol::getAccessName() const {
if (getBasicType() == EbtBlock)
return getType().getTypeName();
else
return getName();
}
//
// Traverse a binary node.
//

View file

@ -1,7 +1,7 @@
//
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2015 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2015-2020 Google, Inc.
// Copyright (C) 2017 ARM Limited.
//
// All rights reserved.
@ -65,7 +65,7 @@ namespace glslang {
// Returns the added node.
//
TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TConstUnionArray& constArray,
TIntermSymbol* TIntermediate::addSymbol(long long id, const TString& name, const TType& type, const TConstUnionArray& constArray,
TIntermTyped* constSubtree, const TSourceLoc& loc)
{
TIntermSymbol* node = new TIntermSymbol(id, name, type);
@ -113,14 +113,14 @@ TIntermSymbol* TIntermediate::addSymbol(const TType& type, const TSourceLoc& loc
//
// Returns nullptr if the working conversions and promotions could not be found.
//
TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc)
TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& loc)
{
// No operations work on blocks
if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock)
return nullptr;
// Convert "reference +/- int" and "reference - reference" to integer math
if ((op == EOpAdd || op == EOpSub) && extensionRequested(E_GL_EXT_buffer_reference2)) {
if (op == EOpAdd || op == EOpSub) {
// No addressing math on struct with unsized array.
if ((left->isReference() && left->getType().getReferentType()->containsUnsizedArray()) ||
@ -140,43 +140,44 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType);
return node;
}
if (op == EOpAdd && right->isReference() && isTypeInt(left->getBasicType())) {
const TType& referenceType = right->getType();
TIntermConstantUnion* size = addConstantUnion((unsigned long long)computeBufferReferenceTypeSize(right->getType()), loc, true);
right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
left = createConversion(EbtInt64, left);
left = addBinaryMath(EOpMul, left, size, loc);
TIntermTyped *node = addBinaryMath(op, left, right, loc);
node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType);
return node;
}
if (op == EOpSub && left->isReference() && right->isReference()) {
TIntermConstantUnion* size = addConstantUnion((long long)computeBufferReferenceTypeSize(left->getType()), loc, true);
left = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, left, TType(EbtUint64));
right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
left = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, left, TType(EbtInt64));
right = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, right, TType(EbtInt64));
left = addBinaryMath(EOpSub, left, right, loc);
TIntermTyped *node = addBinaryMath(EOpDiv, left, size, loc);
return node;
}
// No other math operators supported on references
if (left->isReference() || right->isReference()) {
return nullptr;
}
}
if (op == EOpAdd && right->isReference() && isTypeInt(left->getBasicType())) {
const TType& referenceType = right->getType();
TIntermConstantUnion* size =
addConstantUnion((unsigned long long)computeBufferReferenceTypeSize(right->getType()), loc, true);
right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
left = createConversion(EbtInt64, left);
left = addBinaryMath(EOpMul, left, size, loc);
TIntermTyped *node = addBinaryMath(op, left, right, loc);
node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType);
return node;
}
if (op == EOpSub && left->isReference() && right->isReference()) {
TIntermConstantUnion* size =
addConstantUnion((long long)computeBufferReferenceTypeSize(left->getType()), loc, true);
left = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, left, TType(EbtUint64));
right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
left = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, left, TType(EbtInt64));
right = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, right, TType(EbtInt64));
left = addBinaryMath(EOpSub, left, right, loc);
TIntermTyped *node = addBinaryMath(EOpDiv, left, size, loc);
return node;
}
// No other math operators supported on references
if (left->isReference() || right->isReference())
return nullptr;
// Try converting the children's base types to compatible types.
auto children = addConversion(op, left, right);
auto children = addPairConversion(op, left, right);
left = std::get<0>(children);
right = std::get<1>(children);
@ -226,13 +227,12 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
//
// Low level: add binary node (no promotions or other argument modifications)
//
TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc) const
TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right,
const TSourceLoc& loc) const
{
// build the node
TIntermBinary* node = new TIntermBinary(op);
if (loc.line == 0)
loc = left->getLoc();
node->setLoc(loc);
node->setLoc(loc.line != 0 ? loc : left->getLoc());
node->setLeft(left);
node->setRight(right);
@ -242,7 +242,8 @@ TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TI
//
// like non-type form, but sets node's type.
//
TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc, const TType& type) const
TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right,
const TSourceLoc& loc, const TType& type) const
{
TIntermBinary* node = addBinaryNode(op, left, right, loc);
node->setType(type);
@ -252,12 +253,10 @@ TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TI
//
// Low level: add unary node (no promotions or other argument modifications)
//
TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc) const
TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc& loc) const
{
TIntermUnary* node = new TIntermUnary(op);
if (loc.line == 0)
loc = child->getLoc();
node->setLoc(loc);
node->setLoc(loc.line != 0 ? loc : child->getLoc());
node->setOperand(child);
return node;
@ -266,7 +265,8 @@ TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSo
//
// like non-type form, but sets node's type.
//
TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc, const TType& type) const
TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc& loc, const TType& type)
const
{
TIntermUnary* node = addUnaryNode(op, child, loc);
node->setType(type);
@ -281,7 +281,8 @@ TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSo
// Returns nullptr if the 'right' type could not be converted to match the 'left' type,
// or the resulting operation cannot be properly promoted.
//
TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc)
TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right,
const TSourceLoc& loc)
{
// No block assignment
if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock)
@ -290,9 +291,7 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
// Convert "reference += int" to "reference = reference + int". We need this because the
// "reference + int" calculation involves a cast back to the original type, which makes it
// not an lvalue.
if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference() &&
extensionRequested(E_GL_EXT_buffer_reference2)) {
if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference()) {
if (!(right->getType().isScalar() && right->getType().isIntegerDomain()))
return nullptr;
@ -338,7 +337,8 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
// Returns the added node.
// The caller should set the type of the returned node.
//
TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc loc)
TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index,
const TSourceLoc& loc)
{
// caller should set the type
return addBinaryNode(op, base, index, loc);
@ -349,7 +349,8 @@ TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermT
//
// Returns the added node.
//
TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSourceLoc loc)
TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child,
const TSourceLoc& loc)
{
if (child == 0)
return nullptr;
@ -415,20 +416,24 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSo
// TODO: but, did this bypass constant folding?
//
switch (op) {
case EOpConstructInt8:
case EOpConstructUint8:
case EOpConstructInt16:
case EOpConstructUint16:
case EOpConstructInt:
case EOpConstructUint:
case EOpConstructInt64:
case EOpConstructUint64:
case EOpConstructBool:
case EOpConstructFloat:
case EOpConstructDouble:
case EOpConstructFloat16:
return child;
default: break; // some compilers want this
case EOpConstructInt8:
case EOpConstructUint8:
case EOpConstructInt16:
case EOpConstructUint16:
case EOpConstructInt:
case EOpConstructUint:
case EOpConstructInt64:
case EOpConstructUint64:
case EOpConstructBool:
case EOpConstructFloat:
case EOpConstructDouble:
case EOpConstructFloat16: {
TIntermUnary* unary_node = child->getAsUnaryNode();
if (unary_node != nullptr)
unary_node->updatePrecision();
return child;
}
default: break; // some compilers want this
}
//
@ -495,7 +500,8 @@ TIntermTyped* TIntermediate::addBuiltInFunctionCall(const TSourceLoc& loc, TOper
// Returns an aggregate node, which could be the one passed in if
// it was already an aggregate.
//
TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TType& type, TSourceLoc loc)
TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TType& type,
const TSourceLoc& loc)
{
TIntermAggregate* aggNode;
@ -510,8 +516,6 @@ TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator o
//
aggNode = new TIntermAggregate();
aggNode->getSequence().push_back(node);
if (loc.line == 0)
loc = node->getLoc();
}
} else
aggNode = new TIntermAggregate();
@ -520,8 +524,8 @@ TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator o
// Set the operator.
//
aggNode->setOperator(op);
if (loc.line != 0)
aggNode->setLoc(loc);
if (loc.line != 0 || node != nullptr)
aggNode->setLoc(loc.line != 0 ? loc : node->getLoc());
aggNode->setType(type);
@ -538,7 +542,7 @@ bool TIntermediate::isConversionAllowed(TOperator op, TIntermTyped* node) const
return false;
case EbtAtomicUint:
case EbtSampler:
case EbtAccStructNV:
case EbtAccStruct:
// opaque types can be passed to functions
if (op == EOpFunction)
break;
@ -819,22 +823,25 @@ TIntermTyped* TIntermediate::createConversion(TBasicType convertTo, TIntermTyped
node->getBasicType() == EbtFloat ||
node->getBasicType() == EbtDouble);
if (! getArithemeticInt8Enabled()) {
if (((convertTo == EbtInt8 || convertTo == EbtUint8) && ! convertFromIntTypes) ||
((node->getBasicType() == EbtInt8 || node->getBasicType() == EbtUint8) && ! convertToIntTypes))
if (((convertTo == EbtInt8 || convertTo == EbtUint8) && ! convertFromIntTypes) ||
((node->getBasicType() == EbtInt8 || node->getBasicType() == EbtUint8) && ! convertToIntTypes)) {
if (! getArithemeticInt8Enabled()) {
return nullptr;
}
}
if (! getArithemeticInt16Enabled()) {
if (((convertTo == EbtInt16 || convertTo == EbtUint16) && ! convertFromIntTypes) ||
((node->getBasicType() == EbtInt16 || node->getBasicType() == EbtUint16) && ! convertToIntTypes))
if (((convertTo == EbtInt16 || convertTo == EbtUint16) && ! convertFromIntTypes) ||
((node->getBasicType() == EbtInt16 || node->getBasicType() == EbtUint16) && ! convertToIntTypes)) {
if (! getArithemeticInt16Enabled()) {
return nullptr;
}
}
if (! getArithemeticFloat16Enabled()) {
if ((convertTo == EbtFloat16 && ! convertFromFloatTypes) ||
(node->getBasicType() == EbtFloat16 && ! convertToFloatTypes))
if ((convertTo == EbtFloat16 && ! convertFromFloatTypes) ||
(node->getBasicType() == EbtFloat16 && ! convertToFloatTypes)) {
if (! getArithemeticFloat16Enabled()) {
return nullptr;
}
}
#endif
@ -887,7 +894,7 @@ TIntermTyped* TIntermediate::addConversion(TBasicType convertTo, TIntermTyped* n
// Returns the converted pair of nodes.
// Returns <nullptr, nullptr> when there is no conversion.
std::tuple<TIntermTyped*, TIntermTyped*>
TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1)
TIntermediate::addPairConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1)
{
if (!isConversionAllowed(op, node0) || !isConversionAllowed(op, node1))
return std::make_tuple(nullptr, nullptr);
@ -940,7 +947,7 @@ TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* no
if (node0->getBasicType() == node1->getBasicType())
return std::make_tuple(node0, node1);
promoteTo = getConversionDestinatonType(node0->getBasicType(), node1->getBasicType(), op);
promoteTo = getConversionDestinationType(node0->getBasicType(), node1->getBasicType(), op);
if (std::get<0>(promoteTo) == EbtNumTypes || std::get<1>(promoteTo) == EbtNumTypes)
return std::make_tuple(nullptr, nullptr);
@ -1040,64 +1047,30 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
// Note: callers are responsible for other aspects of shape,
// like vector and matrix sizes.
TBasicType promoteTo;
// GL_EXT_shader_16bit_storage can't do OpConstantComposite with
// 16-bit types, so disable promotion for those types.
bool canPromoteConstant = true;
switch (op) {
//
// Explicit conversions (unary operations)
//
case EOpConstructBool:
promoteTo = EbtBool;
break;
case EOpConstructFloat:
promoteTo = EbtFloat;
break;
case EOpConstructInt:
promoteTo = EbtInt;
break;
case EOpConstructUint:
promoteTo = EbtUint;
break;
#ifndef GLSLANG_WEB
case EOpConstructDouble:
promoteTo = EbtDouble;
break;
case EOpConstructFloat16:
promoteTo = EbtFloat16;
canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16);
break;
case EOpConstructInt8:
promoteTo = EbtInt8;
canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8);
break;
case EOpConstructUint8:
promoteTo = EbtUint8;
canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8);
break;
case EOpConstructInt16:
promoteTo = EbtInt16;
canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16);
break;
case EOpConstructUint16:
promoteTo = EbtUint16;
canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16);
break;
case EOpConstructInt64:
promoteTo = EbtInt64;
break;
case EOpConstructUint64:
promoteTo = EbtUint64;
break;
#endif
//
// Implicit conversions
//
case EOpLogicalNot:
case EOpFunctionCall:
@ -1152,9 +1125,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
if (type.getBasicType() == node->getType().getBasicType())
return node;
if (canImplicitlyPromote(node->getBasicType(), type.getBasicType(), op))
promoteTo = type.getBasicType();
else
if (! canImplicitlyPromote(node->getBasicType(), type.getBasicType(), op))
return nullptr;
break;
@ -1164,9 +1135,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
case EOpLeftShiftAssign:
case EOpRightShiftAssign:
{
if (getSource() == EShSourceHlsl && node->getType().getBasicType() == EbtBool)
promoteTo = type.getBasicType();
else {
if (!(getSource() == EShSourceHlsl && node->getType().getBasicType() == EbtBool)) {
if (isTypeInt(type.getBasicType()) && isTypeInt(node->getBasicType()))
return node;
else
@ -1184,13 +1153,44 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
return nullptr;
}
bool canPromoteConstant = true;
#ifndef GLSLANG_WEB
// GL_EXT_shader_16bit_storage can't do OpConstantComposite with
// 16-bit types, so disable promotion for those types.
// Many issues with this, from JohnK:
// - this isn't really right to discuss SPIR-V here
// - this could easily be entirely about scalars, so is overstepping
// - we should be looking at what the shader asked for, and saying whether or
// not it can be done, in the parser, by calling requireExtensions(), not
// changing language sementics on the fly by asking what extensions are in use
// - at the time of this writing (14-Aug-2020), no test results are changed by this.
switch (op) {
case EOpConstructFloat16:
canPromoteConstant = numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16);
break;
case EOpConstructInt8:
case EOpConstructUint8:
canPromoteConstant = numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8);
break;
case EOpConstructInt16:
case EOpConstructUint16:
canPromoteConstant = numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16);
break;
default:
break;
}
#endif
if (canPromoteConstant && node->getAsConstantUnion())
return promoteConstantUnion(promoteTo, node->getAsConstantUnion());
return promoteConstantUnion(type.getBasicType(), node->getAsConstantUnion());
//
// Add a new newNode for the conversion.
//
TIntermTyped* newNode = createConversion(promoteTo, node);
TIntermTyped* newNode = createConversion(type.getBasicType(), node);
return newNode;
}
@ -1620,7 +1620,7 @@ bool TIntermediate::isFPIntegralConversion(TBasicType from, TBasicType to) const
//
bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op) const
{
if (isEsProfile() || version == 110)
if ((isEsProfile() && version < 310 ) || version == 110)
return false;
if (from == to)
@ -1659,45 +1659,50 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
}
}
bool explicitTypesEnabled = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int32) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int64) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float32) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float64);
if (explicitTypesEnabled) {
// integral promotions
if (isIntegralPromotion(from, to)) {
if (getSource() == EShSourceHlsl) {
// HLSL
if (from == EbtBool && (to == EbtInt || to == EbtUint || to == EbtFloat))
return true;
}
} else {
// GLSL
if (isIntegralPromotion(from, to) ||
isFPPromotion(from, to) ||
isIntegralConversion(from, to) ||
isFPConversion(from, to) ||
isFPIntegralConversion(from, to)) {
// floating-point promotions
if (isFPPromotion(from, to)) {
return true;
}
// integral conversions
if (isIntegralConversion(from, to)) {
return true;
}
// floating-point conversions
if (isFPConversion(from, to)) {
return true;
}
// floating-integral conversions
if (isFPIntegralConversion(from, to)) {
return true;
}
// hlsl supported conversions
if (getSource() == EShSourceHlsl) {
if (from == EbtBool && (to == EbtInt || to == EbtUint || to == EbtFloat))
if (numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int32) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int64) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float32) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float64)) {
return true;
}
}
}
if (isEsProfile()) {
switch (to) {
case EbtFloat:
switch (from) {
case EbtInt:
case EbtUint:
return numericFeatures.contains(TNumericFeatures::shader_implicit_conversions);
default:
return false;
}
case EbtUint:
switch (from) {
case EbtInt:
return numericFeatures.contains(TNumericFeatures::shader_implicit_conversions);
default:
return false;
}
default:
return false;
}
} else {
switch (to) {
@ -1708,13 +1713,14 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
case EbtInt64:
case EbtUint64:
case EbtFloat:
case EbtDouble:
return true;
return version >= 400 || numericFeatures.contains(TNumericFeatures::gpu_shader_fp64);
case EbtInt16:
case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16);
return (version >= 400 || numericFeatures.contains(TNumericFeatures::gpu_shader_fp64)) &&
numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
case EbtFloat16:
return extensionRequested(E_GL_AMD_gpu_shader_half_float);
return (version >= 400 || numericFeatures.contains(TNumericFeatures::gpu_shader_fp64)) &&
numericFeatures.contains(TNumericFeatures::gpu_shader_half_float);
default:
return false;
}
@ -1722,16 +1728,14 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
switch (from) {
case EbtInt:
case EbtUint:
case EbtFloat:
return true;
case EbtBool:
return getSource() == EShSourceHlsl;
case EbtInt16:
case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16);
return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
case EbtFloat16:
return
extensionRequested(E_GL_AMD_gpu_shader_half_float) ||
return numericFeatures.contains(TNumericFeatures::gpu_shader_half_float) ||
getSource() == EShSourceHlsl;
default:
return false;
@ -1739,25 +1743,21 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
case EbtUint:
switch (from) {
case EbtInt:
return version >= 400 || getSource() == EShSourceHlsl;
case EbtUint:
return true;
return version >= 400 || getSource() == EShSourceHlsl || IsRequestedExtension(E_GL_ARB_gpu_shader5);
case EbtBool:
return getSource() == EShSourceHlsl;
case EbtInt16:
case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16);
return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
default:
return false;
}
case EbtInt:
switch (from) {
case EbtInt:
return true;
case EbtBool:
return getSource() == EShSourceHlsl;
case EbtInt16:
return extensionRequested(E_GL_AMD_gpu_shader_int16);
return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
default:
return false;
}
@ -1766,21 +1766,19 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
case EbtInt:
case EbtUint:
case EbtInt64:
case EbtUint64:
return true;
case EbtInt16:
case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16);
return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
default:
return false;
}
case EbtInt64:
switch (from) {
case EbtInt:
case EbtInt64:
return true;
case EbtInt16:
return extensionRequested(E_GL_AMD_gpu_shader_int16);
return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
default:
return false;
}
@ -1788,9 +1786,7 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
switch (from) {
case EbtInt16:
case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16);
case EbtFloat16:
return extensionRequested(E_GL_AMD_gpu_shader_half_float);
return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
default:
break;
}
@ -1798,8 +1794,7 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
case EbtUint16:
switch (from) {
case EbtInt16:
case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16);
return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
default:
break;
}
@ -1926,12 +1921,14 @@ static TBasicType getCorrespondingUnsignedType(TBasicType type)
// integer type corresponding to the type of the operand with signed
// integer type.
std::tuple<TBasicType, TBasicType> TIntermediate::getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const
std::tuple<TBasicType, TBasicType> TIntermediate::getConversionDestinationType(TBasicType type0, TBasicType type1, TOperator op) const
{
TBasicType res0 = EbtNumTypes;
TBasicType res1 = EbtNumTypes;
if (isEsProfile() || version == 110)
if ((isEsProfile() &&
(version < 310 || !numericFeatures.contains(TNumericFeatures::shader_implicit_conversions))) ||
version == 110)
return std::make_tuple(res0, res1);
if (getSource() == EShSourceHlsl) {
@ -2305,6 +2302,10 @@ TOperator TIntermediate::mapTypeToConstructorOp(const TType& type) const
case EbtReference:
op = EOpConstructReference;
break;
case EbtAccStruct:
op = EOpConstructAccStruct;
break;
#endif
default:
break;
@ -2463,7 +2464,7 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true
//
// Get compatible types.
//
auto children = addConversion(EOpSequence, trueBlock, falseBlock);
auto children = addPairConversion(EOpSequence, trueBlock, falseBlock);
trueBlock = std::get<0>(children);
falseBlock = std::get<1>(children);
@ -2679,7 +2680,11 @@ TIntermTyped* TIntermediate::addSwizzle(TSwizzleSelectors<selectorType>& selecto
// 'swizzleOkay' says whether or not it is okay to consider a swizzle
// a valid part of the dereference chain.
//
const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool swizzleOkay)
// 'BufferReferenceOk' says if type is buffer_reference, the routine stop to find the most left node.
//
//
const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool swizzleOkay , bool bufferReferenceOk)
{
do {
const TIntermBinary* binary = node->getAsBinaryNode();
@ -2697,6 +2702,8 @@ const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool
return nullptr;
}
node = node->getAsBinaryNode()->getLeft();
if (bufferReferenceOk && node->isReference())
return node;
} while (true);
}
@ -2750,6 +2757,22 @@ TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expres
return node;
}
// Propagate precision from formal function return type to actual return type,
// and on to its subtree.
void TIntermBranch::updatePrecision(TPrecisionQualifier parentPrecision)
{
TIntermTyped* exp = getExpression();
if (exp == nullptr)
return;
if (exp->getBasicType() == EbtInt || exp->getBasicType() == EbtUint ||
exp->getBasicType() == EbtFloat) {
if (parentPrecision != EpqNone && exp->getQualifier().precision == EpqNone) {
exp->propagatePrecision(parentPrecision);
}
}
}
//
// This is to be executed after the final root is put on top by the parsing
// process.
@ -2774,6 +2797,9 @@ bool TIntermediate::postProcess(TIntermNode* root, EShLanguage /*language*/)
case EShTexSampTransUpgradeTextureRemoveSampler:
performTextureUpgradeAndSamplerRemovalTransformation(root);
break;
case EShTexSampTransCount:
assert(0);
break;
}
#endif
@ -2854,7 +2880,7 @@ void TIntermediate::addToCallGraph(TInfoSink& /*infoSink*/, const TString& calle
return;
}
callGraph.push_front(TCall(caller, callee));
callGraph.emplace_front(caller, callee);
}
//
@ -3234,10 +3260,17 @@ bool TIntermediate::promoteUnary(TIntermUnary& node)
return false;
break;
default:
if (operand->getBasicType() != EbtFloat)
// HLSL uses this path for initial function signature finding for built-ins
// taking a single argument, which generally don't participate in
// operator-based type promotion (type conversion will occur later).
// For now, scalar argument cases are relying on the setType() call below.
if (getSource() == EShSourceHlsl)
break;
// GLSL only allows integer arguments for the cases identified above in the
// case statements.
if (operand->getBasicType() != EbtFloat)
return false;
}
@ -3247,9 +3280,11 @@ bool TIntermediate::promoteUnary(TIntermUnary& node)
return true;
}
// Propagate precision qualifiers *up* from children to parent.
void TIntermUnary::updatePrecision()
{
if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat || getBasicType() == EbtFloat16) {
if (getBasicType() == EbtInt || getBasicType() == EbtUint ||
getBasicType() == EbtFloat) {
if (operand->getQualifier().precision > getQualifier().precision)
getQualifier().precision = operand->getQualifier().precision;
}
@ -3745,20 +3780,55 @@ bool TIntermediate::promoteAggregate(TIntermAggregate& node)
return false;
}
void TIntermBinary::updatePrecision()
// Propagate precision qualifiers *up* from children to parent, and then
// back *down* again to the children's subtrees.
void TIntermAggregate::updatePrecision()
{
if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat || getBasicType() == EbtFloat16) {
getQualifier().precision = std::max(right->getQualifier().precision, left->getQualifier().precision);
if (getQualifier().precision != EpqNone) {
left->propagatePrecision(getQualifier().precision);
right->propagatePrecision(getQualifier().precision);
if (getBasicType() == EbtInt || getBasicType() == EbtUint ||
getBasicType() == EbtFloat) {
TPrecisionQualifier maxPrecision = EpqNone;
TIntermSequence operands = getSequence();
for (unsigned int i = 0; i < operands.size(); ++i) {
TIntermTyped* typedNode = operands[i]->getAsTyped();
assert(typedNode);
maxPrecision = std::max(maxPrecision, typedNode->getQualifier().precision);
}
getQualifier().precision = maxPrecision;
for (unsigned int i = 0; i < operands.size(); ++i) {
TIntermTyped* typedNode = operands[i]->getAsTyped();
assert(typedNode);
typedNode->propagatePrecision(maxPrecision);
}
}
}
// Propagate precision qualifiers *up* from children to parent, and then
// back *down* again to the children's subtrees.
void TIntermBinary::updatePrecision()
{
if (getBasicType() == EbtInt || getBasicType() == EbtUint ||
getBasicType() == EbtFloat) {
if (op == EOpRightShift || op == EOpLeftShift) {
// For shifts get precision from left side only and thus no need to propagate
getQualifier().precision = left->getQualifier().precision;
} else {
getQualifier().precision = std::max(right->getQualifier().precision, left->getQualifier().precision);
if (getQualifier().precision != EpqNone) {
left->propagatePrecision(getQualifier().precision);
right->propagatePrecision(getQualifier().precision);
}
}
}
}
// Recursively propagate precision qualifiers *down* the subtree of the current node,
// until reaching a node that already has a precision qualifier or otherwise does
// not participate in precision propagation.
void TIntermTyped::propagatePrecision(TPrecisionQualifier newPrecision)
{
if (getQualifier().precision != EpqNone || (getBasicType() != EbtInt && getBasicType() != EbtUint && getBasicType() != EbtFloat && getBasicType() != EbtFloat16))
if (getQualifier().precision != EpqNone ||
(getBasicType() != EbtInt && getBasicType() != EbtUint &&
getBasicType() != EbtFloat && getBasicType() != EbtFloat16))
return;
getQualifier().precision = newPrecision;
@ -3832,7 +3902,7 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC
case EbtFloat16: PROMOTE(setDConst, double, Get); break; \
case EbtFloat: PROMOTE(setDConst, double, Get); break; \
case EbtDouble: PROMOTE(setDConst, double, Get); break; \
case EbtInt8: PROMOTE(setI8Const, char, Get); break; \
case EbtInt8: PROMOTE(setI8Const, signed char, Get); break; \
case EbtInt16: PROMOTE(setI16Const, short, Get); break; \
case EbtInt: PROMOTE(setIConst, int, Get); break; \
case EbtInt64: PROMOTE(setI64Const, long long, Get); break; \

View file

@ -74,14 +74,33 @@ public:
for (unsigned int f = 0; f < globals.size(); ++f) {
TIntermAggregate* candidate = globals[f]->getAsAggregate();
if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) {
functions.push_back(candidate);
destinations.push_back(candidate);
break;
}
}
}
typedef std::list<TIntermAggregate*> TFunctionStack;
TFunctionStack functions;
void pushGlobalReference(const TString& name)
{
TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence();
for (unsigned int f = 0; f < globals.size(); ++f) {
TIntermAggregate* candidate = globals[f]->getAsAggregate();
if (candidate && candidate->getOp() == EOpSequence &&
candidate->getSequence().size() == 1 &&
candidate->getSequence()[0]->getAsBinaryNode()) {
TIntermBinary* binary = candidate->getSequence()[0]->getAsBinaryNode();
TIntermSymbol* symbol = binary->getLeft()->getAsSymbolNode();
if (symbol && symbol->getQualifier().storage == EvqGlobal &&
symbol->getName() == name) {
destinations.push_back(candidate);
break;
}
}
}
}
typedef std::list<TIntermAggregate*> TDestinationStack;
TDestinationStack destinations;
protected:
// To catch which function calls are not dead, and hence which functions must be visited.
@ -117,16 +136,27 @@ protected:
// and only visit each function once.
void addFunctionCall(TIntermAggregate* call)
{
// // just use the map to ensure we process each function at most once
// just use the map to ensure we process each function at most once
if (liveFunctions.find(call->getName()) == liveFunctions.end()) {
liveFunctions.insert(call->getName());
pushFunction(call->getName());
}
}
void addGlobalReference(const TString& name)
{
// just use the map to ensure we process each global at most once
if (liveGlobals.find(name) == liveGlobals.end()) {
liveGlobals.insert(name);
pushGlobalReference(name);
}
}
const TIntermediate& intermediate;
typedef std::unordered_set<TString> TLiveFunctions;
TLiveFunctions liveFunctions;
typedef std::unordered_set<TString> TLiveGlobals;
TLiveGlobals liveGlobals;
bool traverseAll;
private:

View file

@ -74,6 +74,9 @@ void C_DECL TParseContextBase::error(const TSourceLoc& loc, const char* szReason
{
if (messages & EShMsgOnlyPreprocessor)
return;
// If enhanced msg readability, only print one error
if (messages & EShMsgEnhanced && numErrors > 0)
return;
va_list args;
va_start(args, szExtraInfoFormat);
outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
@ -127,22 +130,6 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
{
TIntermBinary* binaryNode = node->getAsBinaryNode();
if (binaryNode) {
switch(binaryNode->getOp()) {
case EOpIndexDirect:
case EOpIndexIndirect: // fall through
case EOpIndexDirectStruct: // fall through
case EOpVectorSwizzle:
case EOpMatrixSwizzle:
return lValueErrorCheck(loc, op, binaryNode->getLeft());
default:
break;
}
error(loc, " l-value required", op, "", "");
return true;
}
const char* symbol = nullptr;
TIntermSymbol* symNode = node->getAsSymbolNode();
if (symNode != nullptr)
@ -157,11 +144,11 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
case EvqBuffer:
if (node->getQualifier().isReadOnly())
message = "can't modify a readonly buffer";
if (node->getQualifier().isShaderRecordNV())
if (node->getQualifier().isShaderRecord())
message = "can't modify a shaderrecordnv qualified buffer";
break;
case EvqHitAttrNV:
if (language != EShLangIntersectNV)
case EvqHitAttr:
if (language != EShLangIntersect)
message = "cannot modify hitAttributeNV in this stage";
break;
#endif
@ -181,9 +168,12 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
case EbtAtomicUint:
message = "can't modify an atomic_uint";
break;
case EbtAccStructNV:
case EbtAccStruct:
message = "can't modify accelerationStructureNV";
break;
case EbtRayQuery:
message = "can't modify rayQueryEXT";
break;
#endif
default:
break;
@ -200,15 +190,40 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
// Everything else is okay, no error.
//
if (message == nullptr)
{
if (binaryNode) {
switch (binaryNode->getOp()) {
case EOpIndexDirect:
case EOpIndexIndirect: // fall through
case EOpIndexDirectStruct: // fall through
case EOpVectorSwizzle:
case EOpMatrixSwizzle:
return lValueErrorCheck(loc, op, binaryNode->getLeft());
default:
break;
}
error(loc, " l-value required", op, "", "");
return true;
}
return false;
}
//
// If we get here, we have an error and a message.
//
const TIntermTyped* leftMostTypeNode = TIntermediate::findLValueBase(node, true);
if (symNode)
error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message);
else
error(loc, " l-value required", op, "(%s)", message);
if (binaryNode && binaryNode->getAsOperator()->getOp() == EOpIndexDirectStruct)
if(IsAnonymous(leftMostTypeNode->getAsSymbolNode()->getName()))
error(loc, " l-value required", op, "\"%s\" (%s)", leftMostTypeNode->getAsSymbolNode()->getAccessName().c_str(), message);
else
error(loc, " l-value required", op, "\"%s\" (%s)", leftMostTypeNode->getAsSymbolNode()->getName().c_str(), message);
else
error(loc, " l-value required", op, "(%s)", message);
return true;
}
@ -216,28 +231,41 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
// Test for and give an error if the node can't be read from.
void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
{
TIntermBinary* binaryNode = node->getAsBinaryNode();
const TIntermSymbol* symNode = node->getAsSymbolNode();
if (! node)
return;
TIntermBinary* binaryNode = node->getAsBinaryNode();
if (binaryNode) {
switch(binaryNode->getOp()) {
case EOpIndexDirect:
case EOpIndexIndirect:
case EOpIndexDirectStruct:
case EOpVectorSwizzle:
case EOpMatrixSwizzle:
rValueErrorCheck(loc, op, binaryNode->getLeft());
default:
break;
if (node->getQualifier().isWriteOnly()) {
const TIntermTyped* leftMostTypeNode = TIntermediate::findLValueBase(node, true);
if (symNode != nullptr)
error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str());
else if (binaryNode &&
(binaryNode->getAsOperator()->getOp() == EOpIndexDirectStruct ||
binaryNode->getAsOperator()->getOp() == EOpIndexDirect))
if(IsAnonymous(leftMostTypeNode->getAsSymbolNode()->getName()))
error(loc, "can't read from writeonly object: ", op, leftMostTypeNode->getAsSymbolNode()->getAccessName().c_str());
else
error(loc, "can't read from writeonly object: ", op, leftMostTypeNode->getAsSymbolNode()->getName().c_str());
else
error(loc, "can't read from writeonly object: ", op, "");
} else {
if (binaryNode) {
switch (binaryNode->getOp()) {
case EOpIndexDirect:
case EOpIndexIndirect:
case EOpIndexDirectStruct:
case EOpVectorSwizzle:
case EOpMatrixSwizzle:
rValueErrorCheck(loc, op, binaryNode->getLeft());
default:
break;
}
}
return;
}
TIntermSymbol* symNode = node->getAsSymbolNode();
if (symNode && symNode->getQualifier().isWriteOnly())
error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str());
}
// Add 'symbol' to the list of deferred linkage symbols, which
@ -576,7 +604,6 @@ void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TStrin
selector.push_back(0);
}
#ifdef ENABLE_HLSL
//
// Make the passed-in variable information become a member of the
// global uniform block. If this doesn't exist yet, make it.
@ -598,6 +625,19 @@ void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& mem
globalUniformBlock->getWritableType().getQualifier().layoutBinding = globalUniformBinding;
globalUniformBlock->getWritableType().getQualifier().layoutSet = globalUniformSet;
// Check for declarations of this default uniform that already exist due to other compilation units.
TSymbol* symbol = symbolTable.find(memberName);
if (symbol) {
if (memberType != symbol->getType()) {
TString err;
err += "\"" + memberType.getCompleteString() + "\"";
err += " versus ";
err += "\"" + symbol->getType().getCompleteString() + "\"";
error(loc, "Types must match:", memberType.getFieldName().c_str(), err.c_str());
}
return;
}
// Add the requested member as a member to the global block.
TType* type = new TType;
type->shallowCopy(memberType);
@ -621,7 +661,67 @@ void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& mem
++firstNewMember;
}
#endif
void TParseContextBase::growAtomicCounterBlock(int binding, const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList) {
// Make the atomic counter block, if not yet made.
const auto &at = atomicCounterBuffers.find(binding);
if (at == atomicCounterBuffers.end()) {
atomicCounterBuffers.insert({binding, (TVariable*)nullptr });
atomicCounterBlockFirstNewMember.insert({binding, 0});
}
TVariable*& atomicCounterBuffer = atomicCounterBuffers[binding];
int& bufferNewMember = atomicCounterBlockFirstNewMember[binding];
if (atomicCounterBuffer == nullptr) {
TQualifier blockQualifier;
blockQualifier.clear();
blockQualifier.storage = EvqBuffer;
char charBuffer[512];
if (binding != TQualifier::layoutBindingEnd) {
snprintf(charBuffer, 512, "%s_%d", getAtomicCounterBlockName(), binding);
} else {
snprintf(charBuffer, 512, "%s_0", getAtomicCounterBlockName());
}
TType blockType(new TTypeList, *NewPoolTString(charBuffer), blockQualifier);
setUniformBlockDefaults(blockType);
blockType.getQualifier().layoutPacking = ElpStd430;
atomicCounterBuffer = new TVariable(NewPoolTString(""), blockType, true);
// If we arn't auto mapping bindings then set the block to use the same
// binding as what the atomic was set to use
if (!intermediate.getAutoMapBindings()) {
atomicCounterBuffer->getWritableType().getQualifier().layoutBinding = binding;
}
bufferNewMember = 0;
atomicCounterBuffer->getWritableType().getQualifier().layoutSet = atomicCounterBlockSet;
}
// Add the requested member as a member to the global block.
TType* type = new TType;
type->shallowCopy(memberType);
type->setFieldName(memberName);
if (typeList)
type->setStruct(typeList);
TTypeLoc typeLoc = {type, loc};
atomicCounterBuffer->getType().getWritableStruct()->push_back(typeLoc);
// Insert into the symbol table.
if (bufferNewMember == 0) {
// This is the first request; we need a normal symbol table insert
if (symbolTable.insert(*atomicCounterBuffer))
trackLinkage(*atomicCounterBuffer);
else
error(loc, "failed to insert the global constant buffer", "buffer", "");
} else {
// This is a follow-on request; we need to amend the first insert
symbolTable.amend(*atomicCounterBuffer, bufferNewMember);
}
++bufferNewMember;
}
void TParseContextBase::finish()
{

File diff suppressed because it is too large Load diff

View file

@ -67,7 +67,8 @@ struct TPragma {
class TScanContext;
class TPpContext;
typedef std::set<int> TIdSetType;
typedef std::set<long long> TIdSetType;
typedef std::map<const TTypeList*, std::map<size_t, const TTypeList*>> TStructRecord;
//
// Sharable code (as well as what's in TParseVersions) across
@ -82,7 +83,8 @@ public:
: TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
scopeMangler("::"),
symbolTable(symbolTable),
statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0),
statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), blockNestingLevel(0), controlFlowNestingLevel(0),
currentFunctionType(nullptr),
postEntryPointReturn(false),
contextPragma(true, false),
beginInvocationInterlockCount(0), endInvocationInterlockCount(0),
@ -90,7 +92,8 @@ public:
limits(resources.limits),
globalUniformBlock(nullptr),
globalUniformBinding(TQualifier::layoutBindingEnd),
globalUniformSet(TQualifier::layoutSetEnd)
globalUniformSet(TQualifier::layoutSetEnd),
atomicCounterBlockSet(TQualifier::layoutSetEnd)
{
if (entryPoint != nullptr)
sourceEntryPointName = *entryPoint;
@ -152,10 +155,11 @@ public:
extensionCallback(line, extension, behavior);
}
#ifdef ENABLE_HLSL
// Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
#endif
// Manage global buffer (used for backing atomic counters in GLSL when using relaxed Vulkan semantics)
virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
// Potentially rename shader entry point function
void renameShaderFunction(TString*& name) const
@ -176,7 +180,8 @@ public:
TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
int statementNestingLevel; // 0 if outside all flow control or compound statements
int loopNestingLevel; // 0 if outside all loops
int structNestingLevel; // 0 if outside blocks and structures
int structNestingLevel; // 0 if outside structures
int blockNestingLevel; // 0 if outside blocks
int controlFlowNestingLevel; // 0 if outside all flow control
const TType* currentFunctionType; // the return type of the function that's currently being parsed
bool functionReturnsValue; // true if a non-void function has a return
@ -227,7 +232,25 @@ protected:
// override this to set the language-specific name
virtual const char* getGlobalUniformBlockName() const { return ""; }
virtual void setUniformBlockDefaults(TType&) const { }
virtual void finalizeGlobalUniformBlockLayout(TVariable&) { }
virtual void finalizeGlobalUniformBlockLayout(TVariable&) {}
// Manage the atomic counter block (used for atomic_uints with Vulkan-Relaxed)
TMap<int, TVariable*> atomicCounterBuffers;
unsigned int atomicCounterBlockSet;
TMap<int, int> atomicCounterBlockFirstNewMember;
// override this to set the language-specific name
virtual const char* getAtomicCounterBlockName() const { return ""; }
virtual void setAtomicCounterBlockDefaults(TType&) const {}
virtual void setInvariant(const TSourceLoc&, const char*) {}
virtual void finalizeAtomicCounterBlockLayout(TVariable&) {}
bool isAtomicCounterBlock(const TSymbol& symbol) {
const TVariable* var = symbol.getAsVariable();
if (!var)
return false;
const auto& at = atomicCounterBuffers.find(var->getType().getQualifier().layoutBinding);
return (at != atomicCounterBuffers.end() && (*at).second->getType() == var->getType());
}
virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
const char* szExtraInfoFormat, TPrefixType prefix,
va_list args);
@ -290,6 +313,9 @@ public:
bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override;
void parserError(const char* s); // for bison's yyerror
virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override;
virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override;
void reservedErrorCheck(const TSourceLoc&, const TString&);
void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override;
bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override;
@ -315,6 +341,7 @@ public:
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* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
TIntermTyped* handleDotSwizzle(const TSourceLoc&, 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);
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
@ -326,6 +353,7 @@ public:
TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const;
TIntermTyped* addAssign(const TSourceLoc&, TOperator op, TIntermTyped* left, TIntermTyped* right);
void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&);
void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&);
@ -335,6 +363,10 @@ public:
void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier);
void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode);
TIntermTyped* vkRelaxedRemapFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
// returns true if the variable was remapped to something else
bool vkRelaxedRemapUniformVariable(const TSourceLoc&, TString&, const TPublicType&, TArraySizes*, TIntermTyped*, TType&);
void assignError(const TSourceLoc&, const char* op, TString left, TString right);
void unaryOpError(const TSourceLoc&, const char* op, TString operand);
void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
@ -358,10 +390,10 @@ public:
void boolCheck(const TSourceLoc&, const TPublicType&);
void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer);
void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier);
void accStructNVCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
void memberQualifierCheck(glslang::TPublicType&);
void globalQualifierFixCheck(const TSourceLoc&, TQualifier&);
void globalQualifierFixCheck(const TSourceLoc&, TQualifier&, bool isMemberCheck = false);
void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&);
bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force);
@ -387,7 +419,7 @@ public:
void arrayLimitCheck(const TSourceLoc&, const TString&, int size);
void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature);
void inductiveLoopBodyCheck(TIntermNode*, int loopIndexId, TSymbolTable&);
void inductiveLoopBodyCheck(TIntermNode*, long long loopIndexId, TSymbolTable&);
void constantIndexExpressionCheck(TIntermNode*);
void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&);
@ -412,17 +444,21 @@ public:
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to);
void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
void blockStorageRemap(const TSourceLoc&, const TString*, TQualifier&);
void blockStageIoCheck(const TSourceLoc&, const TQualifier&);
void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName);
void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
void fixXfbOffsets(TQualifier&, TTypeList&);
void fixBlockUniformOffsets(TQualifier&, TTypeList&);
void fixBlockUniformLayoutMatrix(TQualifier&, TTypeList*, TTypeList*);
void fixBlockUniformLayoutPacking(TQualifier&, TTypeList*, TTypeList*);
void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier);
void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
void invariantCheck(const TSourceLoc&, const TQualifier&);
void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
const TTypeList* recordStructCopy(TStructRecord&, const TType*, const TType*);
#ifndef GLSLANG_WEB
TAttributeType attributeFromName(const TString& name) const;
@ -435,6 +471,21 @@ public:
void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*);
// Determine loop control from attributes
void handleLoopAttributes(const TAttributes& attributes, TIntermNode*);
// Function attributes
void handleFunctionAttributes(const TSourceLoc&, const TAttributes&);
// GL_EXT_spirv_intrinsics
TSpirvRequirement* makeSpirvRequirement(const TSourceLoc& loc, const TString& name,
const TIntermAggregate* extensions, const TIntermAggregate* capabilities);
TSpirvRequirement* mergeSpirvRequirements(const TSourceLoc& loc, TSpirvRequirement* spirvReq1,
TSpirvRequirement* spirvReq2);
TSpirvTypeParameters* makeSpirvTypeParameters(const TSourceLoc& loc, const TIntermConstantUnion* constant);
TSpirvTypeParameters* mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1,
TSpirvTypeParameters* spirvTypeParams2);
TSpirvInstruction* makeSpirvInstruction(const TSourceLoc& loc, const TString& name, const TString& value);
TSpirvInstruction* makeSpirvInstruction(const TSourceLoc& loc, const TString& name, int value);
TSpirvInstruction* mergeSpirvInstruction(const TSourceLoc& loc, TSpirvInstruction* spirvInst1,
TSpirvInstruction* spirvInst2);
#endif
void checkAndResizeMeshViewDim(const TSourceLoc&, TType&, bool isBlockMember);
@ -453,6 +504,15 @@ protected:
void finish() override;
#endif
virtual const char* getGlobalUniformBlockName() const override;
virtual void finalizeGlobalUniformBlockLayout(TVariable&) override;
virtual void setUniformBlockDefaults(TType& block) const override;
virtual const char* getAtomicCounterBlockName() const override;
virtual void finalizeAtomicCounterBlockLayout(TVariable&) override;
virtual void setAtomicCounterBlockDefaults(TType& block) const override;
virtual void setInvariant(const TSourceLoc& loc, const char* builtin) override;
public:
//
// Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access
@ -477,12 +537,15 @@ protected:
TQualifier globalUniformDefaults;
TQualifier globalInputDefaults;
TQualifier globalOutputDefaults;
TQualifier globalSharedDefaults;
TString currentCaller; // name of last function body entered (not valid when at global scope)
#ifndef GLSLANG_WEB
int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point
bool anyIndexLimits;
TIdSetType inductiveLoopIds;
TVector<TIntermTyped*> needsIndexLimitationChecking;
TStructRecord matrixFixRecord;
TStructRecord packingFixRecord;
//
// Geometry shader input arrays:

View file

@ -2,6 +2,8 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Copyright (C) 2020 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@ -187,17 +189,15 @@ bool TInputScanner::scanVersion(int& version, EProfile& profile, bool& notFirstT
if (lookingInMiddle) {
notFirstToken = true;
// make forward progress by finishing off the current line plus extra new lines
if (peek() == '\n' || peek() == '\r') {
while (peek() == '\n' || peek() == '\r')
get();
} else
if (peek() != '\n' && peek() != '\r') {
do {
c = get();
} while (c != EndOfInput && c != '\n' && c != '\r');
while (peek() == '\n' || peek() == '\r')
get();
if (peek() == EndOfInput)
return true;
}
while (peek() == '\n' || peek() == '\r')
get();
if (peek() == EndOfInput)
return true;
}
lookingInMiddle = true;
@ -365,6 +365,9 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["if"] = IF;
(*KeywordMap)["else"] = ELSE;
(*KeywordMap)["discard"] = DISCARD;
(*KeywordMap)["terminateInvocation"] = TERMINATE_INVOCATION;
(*KeywordMap)["terminateRayEXT"] = TERMINATE_RAY;
(*KeywordMap)["ignoreIntersectionEXT"] = IGNORE_INTERSECTION;
(*KeywordMap)["return"] = RETURN;
(*KeywordMap)["void"] = VOID;
(*KeywordMap)["bool"] = BOOL;
@ -416,6 +419,7 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["queuefamilycoherent"] = QUEUEFAMILYCOHERENT;
(*KeywordMap)["workgroupcoherent"] = WORKGROUPCOHERENT;
(*KeywordMap)["subgroupcoherent"] = SUBGROUPCOHERENT;
(*KeywordMap)["shadercallcoherent"] = SHADERCALLCOHERENT;
(*KeywordMap)["nonprivate"] = NONPRIVATE;
(*KeywordMap)["restrict"] = RESTRICT;
(*KeywordMap)["readonly"] = READONLY;
@ -470,6 +474,28 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["image2DMSArray"] = IMAGE2DMSARRAY;
(*KeywordMap)["iimage2DMSArray"] = IIMAGE2DMSARRAY;
(*KeywordMap)["uimage2DMSArray"] = UIMAGE2DMSARRAY;
(*KeywordMap)["i64image1D"] = I64IMAGE1D;
(*KeywordMap)["u64image1D"] = U64IMAGE1D;
(*KeywordMap)["i64image2D"] = I64IMAGE2D;
(*KeywordMap)["u64image2D"] = U64IMAGE2D;
(*KeywordMap)["i64image3D"] = I64IMAGE3D;
(*KeywordMap)["u64image3D"] = U64IMAGE3D;
(*KeywordMap)["i64image2DRect"] = I64IMAGE2DRECT;
(*KeywordMap)["u64image2DRect"] = U64IMAGE2DRECT;
(*KeywordMap)["i64imageCube"] = I64IMAGECUBE;
(*KeywordMap)["u64imageCube"] = U64IMAGECUBE;
(*KeywordMap)["i64imageBuffer"] = I64IMAGEBUFFER;
(*KeywordMap)["u64imageBuffer"] = U64IMAGEBUFFER;
(*KeywordMap)["i64image1DArray"] = I64IMAGE1DARRAY;
(*KeywordMap)["u64image1DArray"] = U64IMAGE1DARRAY;
(*KeywordMap)["i64image2DArray"] = I64IMAGE2DARRAY;
(*KeywordMap)["u64image2DArray"] = U64IMAGE2DARRAY;
(*KeywordMap)["i64imageCubeArray"] = I64IMAGECUBEARRAY;
(*KeywordMap)["u64imageCubeArray"] = U64IMAGECUBEARRAY;
(*KeywordMap)["i64image2DMS"] = I64IMAGE2DMS;
(*KeywordMap)["u64image2DMS"] = U64IMAGE2DMS;
(*KeywordMap)["i64image2DMSArray"] = I64IMAGE2DMSARRAY;
(*KeywordMap)["u64image2DMSArray"] = U64IMAGE2DMSARRAY;
(*KeywordMap)["double"] = DOUBLE;
(*KeywordMap)["dvec2"] = DVEC2;
(*KeywordMap)["dvec3"] = DVEC3;
@ -560,6 +586,18 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["f64mat4x2"] = F64MAT4X2;
(*KeywordMap)["f64mat4x3"] = F64MAT4X3;
(*KeywordMap)["f64mat4x4"] = F64MAT4X4;
// GL_EXT_spirv_intrinsics
(*KeywordMap)["spirv_instruction"] = SPIRV_INSTRUCTION;
(*KeywordMap)["spirv_execution_mode"] = SPIRV_EXECUTION_MODE;
(*KeywordMap)["spirv_execution_mode_id"] = SPIRV_EXECUTION_MODE_ID;
(*KeywordMap)["spirv_decorate"] = SPIRV_DECORATE;
(*KeywordMap)["spirv_decorate_id"] = SPIRV_DECORATE_ID;
(*KeywordMap)["spirv_decorate_string"] = SPIRV_DECORATE_STRING;
(*KeywordMap)["spirv_type"] = SPIRV_TYPE;
(*KeywordMap)["spirv_storage_class"] = SPIRV_STORAGE_CLASS;
(*KeywordMap)["spirv_by_reference"] = SPIRV_BY_REFERENCE;
(*KeywordMap)["spirv_literal"] = SPIRV_LITERAL;
#endif
(*KeywordMap)["sampler2D"] = SAMPLER2D;
@ -701,14 +739,22 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["f16subpassInputMS"] = F16SUBPASSINPUTMS;
(*KeywordMap)["__explicitInterpAMD"] = EXPLICITINTERPAMD;
(*KeywordMap)["pervertexNV"] = PERVERTEXNV;
(*KeywordMap)["pervertexEXT"] = PERVERTEXEXT;
(*KeywordMap)["precise"] = PRECISE;
(*KeywordMap)["rayPayloadNV"] = PAYLOADNV;
(*KeywordMap)["rayPayloadEXT"] = PAYLOADEXT;
(*KeywordMap)["rayPayloadInNV"] = PAYLOADINNV;
(*KeywordMap)["rayPayloadInEXT"] = PAYLOADINEXT;
(*KeywordMap)["hitAttributeNV"] = HITATTRNV;
(*KeywordMap)["hitAttributeEXT"] = HITATTREXT;
(*KeywordMap)["callableDataNV"] = CALLDATANV;
(*KeywordMap)["callableDataEXT"] = CALLDATAEXT;
(*KeywordMap)["callableDataInNV"] = CALLDATAINNV;
(*KeywordMap)["callableDataInEXT"] = CALLDATAINEXT;
(*KeywordMap)["accelerationStructureNV"] = ACCSTRUCTNV;
(*KeywordMap)["accelerationStructureEXT"] = ACCSTRUCTEXT;
(*KeywordMap)["rayQueryEXT"] = RAYQUERYEXT;
(*KeywordMap)["perprimitiveNV"] = PERPRIMITIVENV;
(*KeywordMap)["perviewNV"] = PERVIEWNV;
(*KeywordMap)["taskNV"] = PERTASKNV;
@ -843,6 +889,7 @@ int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
parseContext.error(loc, "not supported", "::", "");
break;
case PpAtomConstString: parserToken->sType.lex.string = NewPoolTString(tokenText); return STRING_LITERAL;
case PpAtomConstInt: parserToken->sType.lex.i = ppToken.ival; return INTCONSTANT;
case PpAtomConstUint: parserToken->sType.lex.i = ppToken.ival; return UINTCONSTANT;
case PpAtomConstFloat: parserToken->sType.lex.d = ppToken.dval; return FLOATCONSTANT;
@ -905,10 +952,22 @@ int TScanContext::tokenizeIdentifier()
case CASE:
return keyword;
case TERMINATE_INVOCATION:
if (!parseContext.extensionTurnedOn(E_GL_EXT_terminate_invocation))
return identifierOrType();
return keyword;
case TERMINATE_RAY:
case IGNORE_INTERSECTION:
if (!parseContext.extensionTurnedOn(E_GL_EXT_ray_tracing))
return identifierOrType();
return keyword;
case BUFFER:
afterBuffer = true;
if ((parseContext.isEsProfile() && parseContext.version < 310) ||
(!parseContext.isEsProfile() && parseContext.version < 430))
(!parseContext.isEsProfile() && (parseContext.version < 430 &&
!parseContext.extensionTurnedOn(E_GL_ARB_shader_storage_buffer_object))))
return identifierOrType();
return keyword;
@ -972,7 +1031,7 @@ int TScanContext::tokenizeIdentifier()
return keyword;
case PACKED:
if ((parseContext.isEsProfile() && parseContext.version < 300) ||
(!parseContext.isEsProfile() && parseContext.version < 330))
(!parseContext.isEsProfile() && parseContext.version < 140))
return reservedWord();
return identifierOrType();
@ -1014,6 +1073,23 @@ int TScanContext::tokenizeIdentifier()
parseContext.extensionTurnedOn(E_GL_NV_ray_tracing))
return keyword;
return identifierOrType();
case PAYLOADEXT:
case PAYLOADINEXT:
case HITATTREXT:
case CALLDATAEXT:
case CALLDATAINEXT:
case ACCSTRUCTEXT:
if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_ray_tracing) ||
parseContext.extensionTurnedOn(E_GL_EXT_ray_query))
return keyword;
return identifierOrType();
case RAYQUERYEXT:
if (parseContext.symbolTable.atBuiltInLevel() ||
(!parseContext.isEsProfile() && parseContext.version >= 460
&& parseContext.extensionTurnedOn(E_GL_EXT_ray_query)))
return keyword;
return identifierOrType();
case ATOMIC_UINT:
if ((parseContext.isEsProfile() && parseContext.version >= 310) ||
parseContext.extensionTurnedOn(E_GL_ARB_shader_atomic_counters))
@ -1025,6 +1101,7 @@ int TScanContext::tokenizeIdentifier()
case QUEUEFAMILYCOHERENT:
case WORKGROUPCOHERENT:
case SUBGROUPCOHERENT:
case SHADERCALLCOHERENT:
case NONPRIVATE:
case RESTRICT:
case READONLY:
@ -1119,6 +1196,19 @@ int TScanContext::tokenizeIdentifier()
afterType = true;
return firstGenerationImage(false);
case I64IMAGE1D:
case U64IMAGE1D:
case I64IMAGE1DARRAY:
case U64IMAGE1DARRAY:
case I64IMAGE2DRECT:
case U64IMAGE2DRECT:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) {
return firstGenerationImage(false);
}
return identifierOrType();
case IMAGEBUFFER:
case IIMAGEBUFFER:
case UIMAGEBUFFER:
@ -1128,6 +1218,18 @@ int TScanContext::tokenizeIdentifier()
return keyword;
return firstGenerationImage(false);
case I64IMAGEBUFFER:
case U64IMAGEBUFFER:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) {
if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
return keyword;
return firstGenerationImage(false);
}
return identifierOrType();
case IMAGE2D:
case IIMAGE2D:
case UIMAGE2D:
@ -1143,6 +1245,20 @@ int TScanContext::tokenizeIdentifier()
afterType = true;
return firstGenerationImage(true);
case I64IMAGE2D:
case U64IMAGE2D:
case I64IMAGE3D:
case U64IMAGE3D:
case I64IMAGECUBE:
case U64IMAGECUBE:
case I64IMAGE2DARRAY:
case U64IMAGE2DARRAY:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64))
return firstGenerationImage(true);
return identifierOrType();
case IMAGECUBEARRAY:
case IIMAGECUBEARRAY:
case UIMAGECUBEARRAY:
@ -1152,6 +1268,18 @@ int TScanContext::tokenizeIdentifier()
return keyword;
return secondGenerationImage();
case I64IMAGECUBEARRAY:
case U64IMAGECUBEARRAY:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) {
if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
return keyword;
return secondGenerationImage();
}
return identifierOrType();
case IMAGE2DMS:
case IIMAGE2DMS:
case UIMAGE2DMS:
@ -1161,12 +1289,26 @@ int TScanContext::tokenizeIdentifier()
afterType = true;
return secondGenerationImage();
case I64IMAGE2DMS:
case U64IMAGE2DMS:
case I64IMAGE2DMSARRAY:
case U64IMAGE2DMSARRAY:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) {
return secondGenerationImage();
}
return identifierOrType();
case DOUBLE:
case DVEC2:
case DVEC3:
case DVEC4:
afterType = true;
if (parseContext.isEsProfile() || parseContext.version < 400)
if (parseContext.isEsProfile() || parseContext.version < 150 ||
(!parseContext.symbolTable.atBuiltInLevel() &&
(parseContext.version < 400 && !parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64) &&
(parseContext.version < 410 && !parseContext.extensionTurnedOn(E_GL_ARB_vertex_attrib_64bit)))))
reservedWord();
return keyword;
@ -1578,6 +1720,12 @@ int TScanContext::tokenizeIdentifier()
return keyword;
return identifierOrType();
case PERVERTEXEXT:
if ((!parseContext.isEsProfile() && parseContext.version >= 450) ||
parseContext.extensionTurnedOn(E_GL_EXT_fragment_shader_barycentric))
return keyword;
return identifierOrType();
case PRECISE:
if ((parseContext.isEsProfile() &&
(parseContext.version >= 320 || parseContext.extensionsTurnedOn(Num_AEP_gpu_shader5, AEP_gpu_shader5))) ||
@ -1618,6 +1766,21 @@ int TScanContext::tokenizeIdentifier()
return keyword;
else
return identifierOrType();
case SPIRV_INSTRUCTION:
case SPIRV_EXECUTION_MODE:
case SPIRV_EXECUTION_MODE_ID:
case SPIRV_DECORATE:
case SPIRV_DECORATE_ID:
case SPIRV_DECORATE_STRING:
case SPIRV_TYPE:
case SPIRV_STORAGE_CLASS:
case SPIRV_BY_REFERENCE:
case SPIRV_LITERAL:
if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_spirv_intrinsics))
return keyword;
return identifierOrType();
#endif
default:
@ -1741,7 +1904,11 @@ int TScanContext::dMat()
return keyword;
}
if (!parseContext.isEsProfile() && parseContext.version >= 400)
if (!parseContext.isEsProfile() && (parseContext.version >= 400 ||
parseContext.symbolTable.atBuiltInLevel() ||
(parseContext.version >= 150 && parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64)) ||
(parseContext.version >= 150 && parseContext.extensionTurnedOn(E_GL_ARB_vertex_attrib_64bit)
&& parseContext.language == EShLangVertex)))
return keyword;
if (parseContext.isForwardCompatible())

View file

@ -1,7 +1,7 @@
//
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2013-2016 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2015-2020 Google, Inc.
//
// All rights reserved.
//
@ -51,9 +51,9 @@
#include "ScanContext.h"
#ifdef ENABLE_HLSL
#include "../../hlsl/hlslParseHelper.h"
#include "../../hlsl/hlslParseables.h"
#include "../../hlsl/hlslScanContext.h"
#include "../HLSL/hlslParseHelper.h"
#include "../HLSL/hlslParseables.h"
#include "../HLSL/hlslScanContext.h"
#endif
#include "../Include/ShHandle.h"
@ -72,6 +72,9 @@
// token to print ", but none of that seems appropriate for this file.
#include "preprocessor/PpTokens.h"
// Build-time generated includes
#include "../Include/build_info.h"
namespace { // anonymous namespace for file-local functions and symbols
// Total number of successful initializers of glslang: a refcount
@ -156,7 +159,7 @@ int MapVersionToIndex(int version)
return index;
}
const int SpvVersionCount = 3; // index range in MapSpvVersionToIndex
const int SpvVersionCount = 4; // index range in MapSpvVersionToIndex
int MapSpvVersionToIndex(const SpvVersion& spvVersion)
{
@ -164,8 +167,12 @@ int MapSpvVersionToIndex(const SpvVersion& spvVersion)
if (spvVersion.openGl > 0)
index = 1;
else if (spvVersion.vulkan > 0)
index = 2;
else if (spvVersion.vulkan > 0) {
if (!spvVersion.vulkanRelaxed)
index = 2;
else
index = 3;
}
assert(index < SpvVersionCount);
@ -291,6 +298,9 @@ void InitializeStageSymbolTable(TBuiltInParseables& builtInParseables, int versi
#ifdef GLSLANG_WEB
profile = EEsProfile;
version = 310;
#elif defined(GLSLANG_ANGLE)
profile = ECoreProfile;
version = 450;
#endif
(*symbolTables[language]).adoptLevels(*commonTable[CommonIndex(profile, language)]);
@ -312,6 +322,9 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS
#ifdef GLSLANG_WEB
profile = EEsProfile;
version = 310;
#elif defined(GLSLANG_ANGLE)
profile = ECoreProfile;
version = 450;
#endif
std::unique_ptr<TBuiltInParseables> builtInParseables(CreateBuiltInParseables(infoSink, source));
@ -351,7 +364,6 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS
(profile == EEsProfile && version >= 310))
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangGeometry, source,
infoSink, commonTable, symbolTables);
#endif
// check for compute
if ((profile != EEsProfile && version >= 420) ||
@ -359,19 +371,20 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCompute, source,
infoSink, commonTable, symbolTables);
#ifndef GLSLANG_ANGLE
// check for ray tracing stages
if (profile != EEsProfile && version >= 450) {
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGenNV, source,
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGen, source,
infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersectNV, source,
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersect, source,
infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHitNV, source,
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHit, source,
infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHitNV, source,
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHit, source,
infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMissNV, source,
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMiss, source,
infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallableNV, source,
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallable, source,
infoSink, commonTable, symbolTables);
}
@ -386,6 +399,8 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS
(profile == EEsProfile && version >= 320))
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTaskNV, source,
infoSink, commonTable, symbolTables);
#endif // !GLSLANG_ANGLE
#endif // !GLSLANG_WEB
return true;
}
@ -487,7 +502,7 @@ void SetupBuiltinSymbolTable(int version, EProfile profile, const SpvVersion& sp
// Function to Print all builtins
void DumpBuiltinSymbolTable(TInfoSink& infoSink, const TSymbolTable& symbolTable)
{
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
infoSink.debug << "BuiltinSymbolTable {\n";
symbolTable.dump(infoSink, true);
@ -591,7 +606,7 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
break;
}
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
// Correct for stage type...
switch (stage) {
case EShLangGeometry:
@ -623,12 +638,12 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
version = profile == EEsProfile ? 310 : 420;
}
break;
case EShLangRayGenNV:
case EShLangIntersectNV:
case EShLangAnyHitNV:
case EShLangClosestHitNV:
case EShLangMissNV:
case EShLangCallableNV:
case EShLangRayGen:
case EShLangIntersect:
case EShLangAnyHit:
case EShLangClosestHit:
case EShLangMiss:
case EShLangCallable:
if (profile == EEsProfile || version < 460) {
correct = false;
infoSink.info.message(EPrefixError, "#version: ray tracing shaders require non-es profile with version 460 or above");
@ -712,10 +727,14 @@ void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages
break;
case EShClientVulkan:
spvVersion.vulkanGlsl = environment->input.dialectVersion;
spvVersion.vulkanRelaxed = environment->input.vulkanRulesRelaxed;
break;
case EShClientOpenGL:
spvVersion.openGl = environment->input.dialectVersion;
break;
case EShClientCount:
assert(0);
break;
}
switch (environment->input.languageFamily) {
case EShSourceNone:
@ -728,6 +747,9 @@ void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages
source = EShSourceHlsl;
messages = static_cast<EShMessages>(messages | EShMsgReadHlsl);
break;
case EShSourceCount:
assert(0);
break;
}
}
@ -791,6 +813,7 @@ bool ProcessDeferred(
// set version/profile to defaultVersion/defaultProfile regardless of the #version
// directive in the source code
bool forceDefaultVersionAndProfile,
int overrideVersion, // overrides version specified by #verison or default version
bool forwardCompatible, // give errors for use of deprecated features
EShMessages messages, // warnings/errors/AST; things to print out
TIntermediate& intermediate, // returned tree, etc.
@ -861,7 +884,7 @@ bool ProcessDeferred(
: userInput.scanVersion(version, profile, versionNotFirstToken);
bool versionNotFound = version == 0;
if (forceDefaultVersionAndProfile && source == EShSourceGlsl) {
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
if (! (messages & EShMsgSuppressWarnings) && ! versionNotFound &&
(version != defaultVersion || profile != defaultProfile)) {
compiler->infoSink.info << "Warning, (version, profile) forced to be ("
@ -878,16 +901,22 @@ bool ProcessDeferred(
version = defaultVersion;
profile = defaultProfile;
}
if (source == EShSourceGlsl && overrideVersion != 0) {
version = overrideVersion;
}
bool goodVersion = DeduceVersionProfile(compiler->infoSink, stage,
versionNotFirst, defaultVersion, source, version, profile, spvVersion);
#ifdef GLSLANG_WEB
profile = EEsProfile;
version = 310;
#elif defined(GLSLANG_ANGLE)
profile = ECoreProfile;
version = 450;
#endif
bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst));
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
bool warnVersionNotFirst = false;
if (! versionWillBeError && versionNotFirstToken) {
if (messages & EShMsgRelaxedErrors)
@ -929,6 +958,9 @@ bool ProcessDeferred(
if (cachedTable)
symbolTable->adoptLevels(*cachedTable);
if (intermediate.getUniqueId() != 0)
symbolTable->overwriteUniqueId(intermediate.getUniqueId());
// Add built-in symbols that are potentially context dependent;
// they get popped again further down.
if (! AddContextSpecificSymbols(resources, compiler->infoSink, *symbolTable, version, profile, spvVersion,
@ -957,7 +989,7 @@ bool ProcessDeferred(
parseContext->setLimits(*resources);
if (! goodVersion)
parseContext->addError();
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
if (warnVersionNotFirst) {
TSourceLoc loc;
loc.init();
@ -991,10 +1023,11 @@ bool ProcessDeferred(
bool success = processingContext(*parseContext, ppContext, fullInput,
versionWillBeError, *symbolTable,
intermediate, optLevel, messages);
intermediate.setUniqueId(symbolTable->getMaxSymbolId());
return success;
}
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
// Responsible for keeping track of the most recent source string and line in
// the preprocessor and outputting newlines appropriately if the source string
@ -1217,14 +1250,16 @@ struct DoFullParse{
parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors. No code generated.\n\n";
}
#ifndef GLSLANG_ANGLE
if (messages & EShMsgAST)
intermediate.output(parseContext.infoSink, true);
#endif
return success;
}
};
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
// Take a single compilation unit, and run the preprocessor on it.
// Return: True if there were no issues found in preprocessing,
// False if during preprocessing any unknown version, pragmas or
@ -1244,18 +1279,20 @@ bool PreprocessDeferred(
int defaultVersion, // use 100 for ES environment, 110 for desktop
EProfile defaultProfile,
bool forceDefaultVersionAndProfile,
int overrideVersion, // use 0 if not overriding GLSL version
bool forwardCompatible, // give errors for use of deprecated features
EShMessages messages, // warnings/errors/AST; things to print out
TShader::Includer& includer,
TIntermediate& intermediate, // returned tree, etc.
std::string* outputString)
std::string* outputString,
TEnvironment* environment = nullptr)
{
DoPreprocessing parser(outputString);
return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
preamble, optLevel, resources, defaultVersion,
defaultProfile, forceDefaultVersionAndProfile,
defaultProfile, forceDefaultVersionAndProfile, overrideVersion,
forwardCompatible, messages, intermediate, parser,
false, includer);
false, includer, "", environment);
}
#endif
@ -1282,6 +1319,7 @@ bool CompileDeferred(
int defaultVersion, // use 100 for ES environment, 110 for desktop
EProfile defaultProfile,
bool forceDefaultVersionAndProfile,
int overrideVersion, // use 0 if not overriding GLSL version
bool forwardCompatible, // give errors for use of deprecated features
EShMessages messages, // warnings/errors/AST; things to print out
TIntermediate& intermediate,// returned tree, etc.
@ -1292,7 +1330,7 @@ bool CompileDeferred(
DoFullParse parser;
return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
preamble, optLevel, resources, defaultVersion,
defaultProfile, forceDefaultVersionAndProfile,
defaultProfile, forceDefaultVersionAndProfile, overrideVersion,
forwardCompatible, messages, intermediate, parser,
true, includer, sourceEntryPointName, environment);
}
@ -1311,7 +1349,6 @@ int ShInitialize()
glslang::GetGlobalLock();
++NumberOfClients;
glslang::ReleaseGlobalLock();
if (PerProcessGPA == nullptr)
PerProcessGPA = new TPoolAllocator();
@ -1321,6 +1358,7 @@ int ShInitialize()
glslang::HlslScanContext::fillInKeywordMap();
#endif
glslang::ReleaseGlobalLock();
return 1;
}
@ -1383,9 +1421,10 @@ int ShFinalize()
--NumberOfClients;
assert(NumberOfClients >= 0);
bool finalize = NumberOfClients == 0;
glslang::ReleaseGlobalLock();
if (! finalize)
if (! finalize) {
glslang::ReleaseGlobalLock();
return 1;
}
for (int version = 0; version < VersionCount; ++version) {
for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) {
@ -1423,6 +1462,7 @@ int ShFinalize()
glslang::HlslScanContext::deleteKeywordMap();
#endif
glslang::ReleaseGlobalLock();
return 1;
}
@ -1464,7 +1504,7 @@ int ShCompile(
TIntermediate intermediate(compiler->getLanguage());
TShader::ForbidIncluder includer;
bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, nullptr,
"", optLevel, resources, defaultVersion, ENoProfile, false,
"", optLevel, resources, defaultVersion, ENoProfile, false, 0,
forwardCompatible, messages, intermediate, includer);
//
@ -1678,19 +1718,29 @@ int ShGetUniformLocation(const ShHandle handle, const char* name)
namespace glslang {
#include "../Include/revision.h"
Version GetVersion()
{
Version version;
version.major = GLSLANG_VERSION_MAJOR;
version.minor = GLSLANG_VERSION_MINOR;
version.patch = GLSLANG_VERSION_PATCH;
version.flavor = GLSLANG_VERSION_FLAVOR;
return version;
}
#define QUOTE(s) #s
#define STR(n) QUOTE(n)
const char* GetEsslVersionString()
{
return "OpenGL ES GLSL 3.20 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL);
return "OpenGL ES GLSL 3.20 glslang Khronos. " STR(GLSLANG_VERSION_MAJOR) "." STR(GLSLANG_VERSION_MINOR) "." STR(
GLSLANG_VERSION_PATCH) GLSLANG_VERSION_FLAVOR;
}
const char* GetGlslVersionString()
{
return "4.60 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL);
return "4.60 glslang Khronos. " STR(GLSLANG_VERSION_MAJOR) "." STR(GLSLANG_VERSION_MINOR) "." STR(
GLSLANG_VERSION_PATCH) GLSLANG_VERSION_FLAVOR;
}
int GetKhronosToolId()
@ -1715,7 +1765,7 @@ public:
};
TShader::TShader(EShLanguage s)
: stage(s), lengths(nullptr), stringNames(nullptr), preamble("")
: stage(s), lengths(nullptr), stringNames(nullptr), preamble(""), overrideVersion(0)
{
pool = new TPoolAllocator;
infoSink = new TInfoSink;
@ -1725,6 +1775,7 @@ TShader::TShader(EShLanguage s)
// clear environment (avoid constructors in them for use in a C interface)
environment.input.languageFamily = EShSourceNone;
environment.input.dialect = EShClientNone;
environment.input.vulkanRulesRelaxed = false;
environment.client.client = EShClientNone;
environment.target.language = EShTargetNone;
environment.target.hlslFunctionality1 = false;
@ -1771,12 +1822,26 @@ void TShader::setSourceEntryPoint(const char* name)
sourceEntryPointName = name;
}
// Log initial settings and transforms.
// See comment for class TProcesses.
void TShader::addProcesses(const std::vector<std::string>& p)
{
intermediate->addProcesses(p);
}
void TShader::setUniqueId(unsigned long long id)
{
intermediate->setUniqueId(id);
}
void TShader::setOverrideVersion(int version)
{
overrideVersion = version;
}
void TShader::setInvertY(bool invert) { intermediate->setInvertY(invert); }
void TShader::setDxPositionW(bool invert) { intermediate->setDxPositionW(invert); }
void TShader::setEnhancedMsgs() { intermediate->setEnhancedMsgs(); }
void TShader::setNanMinMaxClamp(bool useNonNan) { intermediate->setNanMinMaxClamp(useNonNan); }
#ifndef GLSLANG_WEB
@ -1824,6 +1889,15 @@ void TShader::setResourceSetBinding(const std::vector<std::string>& base) { in
void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); }
#endif
void TShader::addBlockStorageOverride(const char* nameStr, TBlockStorageClass backing) { intermediate->addBlockStorageOverride(nameStr, backing); }
void TShader::setGlobalUniformBlockName(const char* name) { intermediate->setGlobalUniformBlockName(name); }
void TShader::setGlobalUniformSet(unsigned int set) { intermediate->setGlobalUniformSet(set); }
void TShader::setGlobalUniformBinding(unsigned int binding) { intermediate->setGlobalUniformBinding(binding); }
void TShader::setAtomicCounterBlockName(const char* name) { intermediate->setAtomicCounterBlockName(name); }
void TShader::setAtomicCounterBlockSet(unsigned int set) { intermediate->setAtomicCounterBlockSet(set); }
#ifdef ENABLE_HLSL
// See comment above TDefaultHlslIoMapper in iomapper.cpp:
void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslIoMapping(hlslIoMap); }
@ -1847,12 +1921,12 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion
return CompileDeferred(compiler, strings, numStrings, lengths, stringNames,
preamble, EShOptNone, builtInResources, defaultVersion,
defaultProfile, forceDefaultVersionAndProfile,
defaultProfile, forceDefaultVersionAndProfile, overrideVersion,
forwardCompatible, messages, *intermediate, includer, sourceEntryPointName,
&environment);
}
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
// Fill in a string with the result of preprocessing ShaderStrings
// Returns true if all extensions, pragmas and version strings were valid.
//
@ -1874,8 +1948,9 @@ bool TShader::preprocess(const TBuiltInResource* builtInResources,
return PreprocessDeferred(compiler, strings, numStrings, lengths, stringNames, preamble,
EShOptNone, builtInResources, defaultVersion,
defaultProfile, forceDefaultVersionAndProfile,
forwardCompatible, message, includer, *intermediate, output_string);
defaultProfile, forceDefaultVersionAndProfile, overrideVersion,
forwardCompatible, message, includer, *intermediate, output_string,
&environment);
}
#endif
@ -1890,7 +1965,7 @@ const char* TShader::getInfoDebugLog()
}
TProgram::TProgram() :
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
reflection(0),
#endif
linked(false)
@ -1906,7 +1981,7 @@ TProgram::TProgram() :
TProgram::~TProgram()
{
delete infoSink;
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
delete reflection;
#endif
@ -1938,7 +2013,10 @@ bool TProgram::link(EShMessages messages)
error = true;
}
// TODO: Link: cross-stage error checking
if (!error) {
if (! crossStageCheck(messages))
error = true;
}
return ! error;
}
@ -1953,7 +2031,7 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
if (stages[stage].size() == 0)
return true;
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
int numEsShaders = 0, numNonEsShaders = 0;
for (auto it = stages[stage].begin(); it != stages[stage].end(); ++it) {
if ((*it)->intermediate->getProfile() == EEsProfile) {
@ -1982,7 +2060,9 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
intermediate[stage] = new TIntermediate(stage,
firstIntermediate->getVersion(),
firstIntermediate->getProfile());
intermediate[stage]->setLimits(firstIntermediate->getLimits());
if (firstIntermediate->getEnhancedMsgs())
intermediate[stage]->setEnhancedMsgs();
// The new TIntermediate must use the same origin as the original TIntermediates.
// Otherwise linking will fail due to different coordinate systems.
@ -2007,12 +2087,77 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
#endif
intermediate[stage]->finalCheck(*infoSink, (messages & EShMsgKeepUncalled) != 0);
#ifndef GLSLANG_ANGLE
if (messages & EShMsgAST)
intermediate[stage]->output(*infoSink, true);
#endif
return intermediate[stage]->getNumErrors() == 0;
}
//
// Check that there are no errors in linker objects accross stages
//
// Return true if no errors.
//
bool TProgram::crossStageCheck(EShMessages) {
// make temporary intermediates to hold the linkage symbols for each linking interface
// while we do the checks
// Independent interfaces are:
// all uniform variables and blocks
// all buffer blocks
// all in/out on a stage boundary
TVector<TIntermediate*> activeStages;
for (int s = 0; s < EShLangCount; ++s) {
if (intermediate[s])
activeStages.push_back(intermediate[s]);
}
// no extra linking if there is only one stage
if (! (activeStages.size() > 1))
return true;
// setup temporary tree to hold unfirom objects from different stages
TIntermediate* firstIntermediate = activeStages.front();
TIntermediate uniforms(EShLangCount,
firstIntermediate->getVersion(),
firstIntermediate->getProfile());
uniforms.setSpv(firstIntermediate->getSpv());
TIntermAggregate uniformObjects(EOpLinkerObjects);
TIntermAggregate root(EOpSequence);
root.getSequence().push_back(&uniformObjects);
uniforms.setTreeRoot(&root);
bool error = false;
// merge uniforms from all stages into a single intermediate
for (unsigned int i = 0; i < activeStages.size(); ++i) {
uniforms.mergeUniformObjects(*infoSink, *activeStages[i]);
}
error |= uniforms.getNumErrors() != 0;
// copy final definition of global block back into each stage
for (unsigned int i = 0; i < activeStages.size(); ++i) {
// We only want to merge into already existing global uniform blocks.
// A stage that doesn't already know about the global doesn't care about it's content.
// Otherwise we end up pointing to the same object between different stages
// and that will break binding/set remappings
bool mergeExistingOnly = true;
activeStages[i]->mergeGlobalUniformBlocks(*infoSink, uniforms, mergeExistingOnly);
}
// compare cross stage symbols for each stage boundary
for (unsigned int i = 1; i < activeStages.size(); ++i) {
activeStages[i - 1]->checkStageIO(*infoSink, *activeStages[i]);
error |= (activeStages[i - 1]->getNumErrors() != 0);
}
return !error;
}
const char* TProgram::getInfoLog()
{
return infoSink->info.c_str();
@ -2023,7 +2168,7 @@ const char* TProgram::getInfoDebugLog()
return infoSink->debug.c_str();
}
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
//
// Reflection implementation.
@ -2105,6 +2250,6 @@ bool TProgram::mapIO(TIoMapResolver* pResolver, TIoMapper* pIoMapper)
return ioMapper->doMap(pResolver, *infoSink);
}
#endif // GLSLANG_WEB
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
} // end namespace glslang

View file

@ -0,0 +1,350 @@
//
// Copyright(C) 2021 Advanced Micro Devices, 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.
//
#ifndef GLSLANG_WEB
//
// GL_EXT_spirv_intrinsics
//
#include "../Include/intermediate.h"
#include "../Include/SpirvIntrinsics.h"
#include "../Include/Types.h"
#include "ParseHelper.h"
namespace glslang {
//
// Handle SPIR-V requirements
//
TSpirvRequirement* TParseContext::makeSpirvRequirement(const TSourceLoc& loc, const TString& name,
const TIntermAggregate* extensions,
const TIntermAggregate* capabilities)
{
TSpirvRequirement* spirvReq = new TSpirvRequirement;
if (name == "extensions") {
assert(extensions);
for (auto extension : extensions->getSequence()) {
assert(extension->getAsConstantUnion());
spirvReq->extensions.insert(*extension->getAsConstantUnion()->getConstArray()[0].getSConst());
}
} else if (name == "capabilities") {
assert(capabilities);
for (auto capability : capabilities->getSequence()) {
assert(capability->getAsConstantUnion());
spirvReq->capabilities.insert(capability->getAsConstantUnion()->getConstArray()[0].getIConst());
}
} else
error(loc, "unknow SPIR-V requirement", name.c_str(), "");
return spirvReq;
}
TSpirvRequirement* TParseContext::mergeSpirvRequirements(const TSourceLoc& loc, TSpirvRequirement* spirvReq1,
TSpirvRequirement* spirvReq2)
{
// Merge the second SPIR-V requirement to the first one
if (!spirvReq2->extensions.empty()) {
if (spirvReq1->extensions.empty())
spirvReq1->extensions = spirvReq2->extensions;
else
error(loc, "too many SPIR-V requirements", "extensions", "");
}
if (!spirvReq2->capabilities.empty()) {
if (spirvReq1->capabilities.empty())
spirvReq1->capabilities = spirvReq2->capabilities;
else
error(loc, "too many SPIR-V requirements", "capabilities", "");
}
return spirvReq1;
}
void TIntermediate::insertSpirvRequirement(const TSpirvRequirement* spirvReq)
{
if (!spirvRequirement)
spirvRequirement = new TSpirvRequirement;
for (auto extension : spirvReq->extensions)
spirvRequirement->extensions.insert(extension);
for (auto capability : spirvReq->capabilities)
spirvRequirement->capabilities.insert(capability);
}
//
// Handle SPIR-V execution modes
//
void TIntermediate::insertSpirvExecutionMode(int executionMode, const TIntermAggregate* args)
{
if (!spirvExecutionMode)
spirvExecutionMode = new TSpirvExecutionMode;
TVector<const TIntermConstantUnion*> extraOperands;
if (args) {
for (auto arg : args->getSequence()) {
auto extraOperand = arg->getAsConstantUnion();
assert(extraOperand != nullptr);
extraOperands.push_back(extraOperand);
}
}
spirvExecutionMode->modes[executionMode] = extraOperands;
}
void TIntermediate::insertSpirvExecutionModeId(int executionMode, const TIntermAggregate* args)
{
if (!spirvExecutionMode)
spirvExecutionMode = new TSpirvExecutionMode;
assert(args);
TVector<const TIntermTyped*> extraOperands;
for (auto arg : args->getSequence()) {
auto extraOperand = arg->getAsTyped();
assert(extraOperand != nullptr && extraOperand->getQualifier().isConstant());
extraOperands.push_back(extraOperand);
}
spirvExecutionMode->modeIds[executionMode] = extraOperands;
}
//
// Handle SPIR-V decorate qualifiers
//
void TQualifier::setSpirvDecorate(int decoration, const TIntermAggregate* args)
{
if (!spirvDecorate)
spirvDecorate = new TSpirvDecorate;
TVector<const TIntermConstantUnion*> extraOperands;
if (args) {
for (auto arg : args->getSequence()) {
auto extraOperand = arg->getAsConstantUnion();
assert(extraOperand != nullptr);
extraOperands.push_back(extraOperand);
}
}
spirvDecorate->decorates[decoration] = extraOperands;
}
void TQualifier::setSpirvDecorateId(int decoration, const TIntermAggregate* args)
{
if (!spirvDecorate)
spirvDecorate = new TSpirvDecorate;
assert(args);
TVector<const TIntermTyped*> extraOperands;
for (auto arg : args->getSequence()) {
auto extraOperand = arg->getAsTyped();
assert(extraOperand != nullptr && extraOperand->getQualifier().isConstant());
extraOperands.push_back(extraOperand);
}
spirvDecorate->decorateIds[decoration] = extraOperands;
}
void TQualifier::setSpirvDecorateString(int decoration, const TIntermAggregate* args)
{
if (!spirvDecorate)
spirvDecorate = new TSpirvDecorate;
assert(args);
TVector<const TIntermConstantUnion*> extraOperands;
for (auto arg : args->getSequence()) {
auto extraOperand = arg->getAsConstantUnion();
assert(extraOperand != nullptr);
extraOperands.push_back(extraOperand);
}
spirvDecorate->decorateStrings[decoration] = extraOperands;
}
TString TQualifier::getSpirvDecorateQualifierString() const
{
assert(spirvDecorate);
TString qualifierString;
const auto appendFloat = [&](float f) { qualifierString.append(std::to_string(f).c_str()); };
const auto appendInt = [&](int i) { qualifierString.append(std::to_string(i).c_str()); };
const auto appendUint = [&](unsigned int u) { qualifierString.append(std::to_string(u).c_str()); };
const auto appendBool = [&](bool b) { qualifierString.append(std::to_string(b).c_str()); };
const auto appendStr = [&](const char* s) { qualifierString.append(s); };
const auto appendDecorate = [&](const TIntermTyped* constant) {
auto& constArray = constant->getAsConstantUnion() != nullptr ? constant->getAsConstantUnion()->getConstArray()
: constant->getAsSymbolNode()->getConstArray();
if (constant->getBasicType() == EbtFloat) {
float value = static_cast<float>(constArray[0].getDConst());
appendFloat(value);
}
else if (constant->getBasicType() == EbtInt) {
int value = constArray[0].getIConst();
appendInt(value);
}
else if (constant->getBasicType() == EbtUint) {
unsigned value = constArray[0].getUConst();
appendUint(value);
}
else if (constant->getBasicType() == EbtBool) {
bool value = constArray[0].getBConst();
appendBool(value);
}
else if (constant->getBasicType() == EbtString) {
const TString* value = constArray[0].getSConst();
appendStr(value->c_str());
}
else
assert(0);
};
for (auto& decorate : spirvDecorate->decorates) {
appendStr("spirv_decorate(");
appendInt(decorate.first);
for (auto extraOperand : decorate.second) {
appendStr(", ");
appendDecorate(extraOperand);
}
appendStr(") ");
}
for (auto& decorateId : spirvDecorate->decorateIds) {
appendStr("spirv_decorate_id(");
appendInt(decorateId.first);
for (auto extraOperand : decorateId.second) {
appendStr(", ");
appendDecorate(extraOperand);
}
appendStr(") ");
}
for (auto& decorateString : spirvDecorate->decorateStrings) {
appendStr("spirv_decorate_string(");
appendInt(decorateString.first);
for (auto extraOperand : decorateString.second) {
appendStr(", ");
appendDecorate(extraOperand);
}
appendStr(") ");
}
return qualifierString;
}
//
// Handle SPIR-V type specifiers
//
void TPublicType::setSpirvType(const TSpirvInstruction& spirvInst, const TSpirvTypeParameters* typeParams)
{
if (!spirvType)
spirvType = new TSpirvType;
basicType = EbtSpirvType;
spirvType->spirvInst = spirvInst;
if (typeParams)
spirvType->typeParams = *typeParams;
}
TSpirvTypeParameters* TParseContext::makeSpirvTypeParameters(const TSourceLoc& loc, const TIntermConstantUnion* constant)
{
TSpirvTypeParameters* spirvTypeParams = new TSpirvTypeParameters;
if (constant->getBasicType() != EbtFloat &&
constant->getBasicType() != EbtInt &&
constant->getBasicType() != EbtUint &&
constant->getBasicType() != EbtBool &&
constant->getBasicType() != EbtString)
error(loc, "this type not allowed", constant->getType().getBasicString(), "");
else {
assert(constant);
spirvTypeParams->push_back(TSpirvTypeParameter(constant));
}
return spirvTypeParams;
}
TSpirvTypeParameters* TParseContext::mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1, TSpirvTypeParameters* spirvTypeParams2)
{
// Merge SPIR-V type parameters of the second one to the first one
for (const auto& spirvTypeParam : *spirvTypeParams2)
spirvTypeParams1->push_back(spirvTypeParam);
return spirvTypeParams1;
}
//
// Handle SPIR-V instruction qualifiers
//
TSpirvInstruction* TParseContext::makeSpirvInstruction(const TSourceLoc& loc, const TString& name, const TString& value)
{
TSpirvInstruction* spirvInst = new TSpirvInstruction;
if (name == "set")
spirvInst->set = value;
else
error(loc, "unknown SPIR-V instruction qualifier", name.c_str(), "");
return spirvInst;
}
TSpirvInstruction* TParseContext::makeSpirvInstruction(const TSourceLoc& loc, const TString& name, int value)
{
TSpirvInstruction* spirvInstuction = new TSpirvInstruction;
if (name == "id")
spirvInstuction->id = value;
else
error(loc, "unknown SPIR-V instruction qualifier", name.c_str(), "");
return spirvInstuction;
}
TSpirvInstruction* TParseContext::mergeSpirvInstruction(const TSourceLoc& loc, TSpirvInstruction* spirvInst1, TSpirvInstruction* spirvInst2)
{
// Merge qualifiers of the second SPIR-V instruction to those of the first one
if (!spirvInst2->set.empty()) {
if (spirvInst1->set.empty())
spirvInst1->set = spirvInst2->set;
else
error(loc, "too many SPIR-V instruction qualifiers", "spirv_instruction", "(set)");
}
if (spirvInst2->id != -1) {
if (spirvInst1->id == -1)
spirvInst1->id = spirvInst2->id;
else
error(loc, "too many SPIR-V instruction qualifiers", "spirv_instruction", "(id)");
}
return spirvInst1;
}
} // end namespace glslang
#endif // GLSLANG_WEB

View file

@ -3,6 +3,7 @@
// Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@ -74,7 +75,9 @@ void TType::buildMangledName(TString& mangledName) const
case EbtInt64: mangledName += "i64"; break;
case EbtUint64: mangledName += "u64"; break;
case EbtAtomicUint: mangledName += "au"; break;
case EbtAccStructNV: mangledName += "asnv"; break;
case EbtAccStruct: mangledName += "as"; break;
case EbtRayQuery: mangledName += "rq"; break;
case EbtSpirvType: mangledName += "spv-t"; break;
#endif
case EbtSampler:
switch (sampler.type) {
@ -83,6 +86,8 @@ void TType::buildMangledName(TString& mangledName) const
#endif
case EbtInt: mangledName += "i"; break;
case EbtUint: mangledName += "u"; break;
case EbtInt64: mangledName += "i64"; break;
case EbtUint64: mangledName += "u64"; break;
default: break; // some compilers want this
}
if (sampler.isImageClass())
@ -120,7 +125,7 @@ void TType::buildMangledName(TString& mangledName) const
mangledName += "-tx-struct";
char text[16]; // plenty enough space for the small integers.
snprintf(text, sizeof(text), "%d-", sampler.getStructReturnIndex());
snprintf(text, sizeof(text), "%u-", sampler.getStructReturnIndex());
mangledName += text;
} else {
switch (sampler.getVectorSize()) {
@ -144,6 +149,8 @@ void TType::buildMangledName(TString& mangledName) const
if (typeName)
mangledName += *typeName;
for (unsigned int i = 0; i < structure->size(); ++i) {
if ((*structure)[i].type->getBasicType() == EbtVoid)
continue;
mangledName += '-';
(*structure)[i].type->buildMangledName(mangledName);
}
@ -164,7 +171,7 @@ void TType::buildMangledName(TString& mangledName) const
for (int i = 0; i < arraySizes->getNumDims(); ++i) {
if (arraySizes->getDimNode(i)) {
if (arraySizes->getDimNode(i)->getAsSymbolNode())
snprintf(buf, maxSize, "s%d", arraySizes->getDimNode(i)->getAsSymbolNode()->getId());
snprintf(buf, maxSize, "s%lld", arraySizes->getDimNode(i)->getAsSymbolNode()->getId());
else
snprintf(buf, maxSize, "s%p", arraySizes->getDimNode(i));
} else
@ -176,7 +183,7 @@ void TType::buildMangledName(TString& mangledName) const
}
}
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
//
// Dump functions.
@ -272,8 +279,14 @@ TFunction::~TFunction()
//
TSymbolTableLevel::~TSymbolTableLevel()
{
for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
delete (*it).second;
for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
const TString& name = it->first;
auto retargetIter = std::find_if(retargetedSymbols.begin(), retargetedSymbols.end(),
[&name](const std::pair<TString, TString>& i) { return i.first == name; });
if (retargetIter == retargetedSymbols.end())
delete (*it).second;
}
delete [] defaultPrecision;
}
@ -384,6 +397,9 @@ TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf)
implicitThis = copyOf.implicitThis;
illegalImplicitThis = copyOf.illegalImplicitThis;
defaultParamCount = copyOf.defaultParamCount;
#ifndef GLSLANG_WEB
spirvInst = copyOf.spirvInst;
#endif
}
TFunction* TFunction::clone() const
@ -408,6 +424,10 @@ TSymbolTableLevel* TSymbolTableLevel::clone() const
TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
symTableLevel->anonId = anonId;
symTableLevel->thisLevel = thisLevel;
symTableLevel->retargetedSymbols.clear();
for (auto &s : retargetedSymbols) {
symTableLevel->retargetedSymbols.push_back({s.first, s.second});
}
std::vector<bool> containerCopied(anonId, false);
tLevel::const_iterator iter;
for (iter = level.begin(); iter != level.end(); ++iter) {
@ -423,8 +443,21 @@ TSymbolTableLevel* TSymbolTableLevel::clone() const
symTableLevel->insert(*container, false);
containerCopied[anon->getAnonId()] = true;
}
} else
} else {
const TString& name = iter->first;
auto retargetIter = std::find_if(retargetedSymbols.begin(), retargetedSymbols.end(),
[&name](const std::pair<TString, TString>& i) { return i.first == name; });
if (retargetIter != retargetedSymbols.end())
continue;
symTableLevel->insert(*iter->second->clone(), false);
}
}
// Now point retargeted symbols to the newly created versions of them
for (auto &s : retargetedSymbols) {
TSymbol* sym = symTableLevel->find(s.second);
if (!sym)
continue;
symTableLevel->insert(s.first, sym);
}
return symTableLevel;

View file

@ -84,7 +84,7 @@ typedef TVector<const char*> TExtensionList;
class TSymbol {
public:
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
explicit TSymbol(const TString *n) : name(n), extensions(0), writable(true) { }
explicit TSymbol(const TString *n) : name(n), uniqueId(0), extensions(0), writable(true) { }
virtual TSymbol* clone() const = 0;
virtual ~TSymbol() { } // rely on all symbol owned memory coming from the pool
@ -104,8 +104,8 @@ public:
virtual const TAnonMember* getAsAnonMember() const { return 0; }
virtual const TType& getType() const = 0;
virtual TType& getWritableType() = 0;
virtual void setUniqueId(int id) { uniqueId = id; }
virtual int getUniqueId() const { return uniqueId; }
virtual void setUniqueId(long long id) { uniqueId = id; }
virtual long long getUniqueId() const { return uniqueId; }
virtual void setExtensions(int numExts, const char* const exts[])
{
assert(extensions == 0);
@ -117,7 +117,7 @@ public:
virtual int getNumExtensions() const { return extensions == nullptr ? 0 : (int)extensions->size(); }
virtual const char** getExtensions() const { return extensions->data(); }
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
virtual void dump(TInfoSink& infoSink, bool complete = false) const = 0;
void dumpExtensions(TInfoSink& infoSink) const;
#endif
@ -130,7 +130,7 @@ protected:
TSymbol& operator=(const TSymbol&);
const TString *name;
unsigned int uniqueId; // For cross-scope comparing during code generation
unsigned long long uniqueId; // For cross-scope comparing during code generation
// For tracking what extensions must be present
// (don't use if correct version/profile is present).
@ -196,7 +196,7 @@ public:
}
virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); }
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
virtual void dump(TInfoSink& infoSink, bool complete = false) const;
#endif
@ -320,6 +320,15 @@ public:
virtual const TParameter& operator[](int i) const { return parameters[i]; }
#ifndef GLSLANG_WEB
virtual void setSpirvInstruction(const TSpirvInstruction& inst)
{
relateToOperator(EOpSpirvInst);
spirvInst = inst;
}
virtual const TSpirvInstruction& getSpirvInstruction() const { return spirvInst; }
#endif
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
#endif
@ -342,6 +351,10 @@ protected:
// This is important for a static member function that has member variables in scope,
// but is not allowed to use them, or see hidden symbols instead.
int defaultParamCount;
#ifndef GLSLANG_WEB
TSpirvInstruction spirvInst; // SPIR-V instruction qualifiers
#endif
};
//
@ -381,7 +394,7 @@ public:
virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); }
virtual int getAnonId() const { return anonId; }
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
#endif
@ -400,13 +413,20 @@ public:
TSymbolTableLevel() : defaultPrecision(0), anonId(0), thisLevel(false) { }
~TSymbolTableLevel();
bool insert(TSymbol& symbol, bool separateNameSpaces)
bool insert(const TString& name, TSymbol* symbol) {
return level.insert(tLevelPair(name, symbol)).second;
}
bool insert(TSymbol& symbol, bool separateNameSpaces, const TString& forcedKeyName = TString())
{
//
// returning true means symbol was added to the table with no semantic errors
//
const TString& name = symbol.getName();
if (name == "") {
if (forcedKeyName.length()) {
return level.insert(tLevelPair(forcedKeyName, &symbol)).second;
}
else if (name == "") {
symbol.getAsVariable()->setAnonId(anonId++);
// An empty name means an anonymous container, exposing its members to the external scope.
// Give it a name and insert its members in the symbol table, pointing to the container.
@ -458,6 +478,16 @@ public:
return true;
}
void retargetSymbol(const TString& from, const TString& to) {
tLevel::const_iterator fromIt = level.find(from);
tLevel::const_iterator toIt = level.find(to);
if (fromIt == level.end() || toIt == level.end())
return;
delete fromIt->second;
level[from] = toIt->second;
retargetedSymbols.push_back({from, to});
}
TSymbol* find(const TString& name) const
{
tLevel::const_iterator it = level.find(name);
@ -551,7 +581,7 @@ public:
void relateToOperator(const char* name, TOperator op);
void setFunctionExtensions(const char* name, int num, const char* const extensions[]);
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
void dump(TInfoSink& infoSink, bool complete = false) const;
#endif
TSymbolTableLevel* clone() const;
@ -570,6 +600,8 @@ protected:
tLevel level; // named mappings
TPrecisionQualifier *defaultPrecision;
// pair<FromName, ToName>
TVector<std::pair<TString, TString>> retargetedSymbols;
int anonId;
bool thisLevel; // True if this level of the symbol table is a structure scope containing member function
// that are supposed to see anonymous access to member variables.
@ -612,21 +644,28 @@ public:
// 3: user-shader globals
//
protected:
static const uint32_t LevelFlagBitOffset = 56;
static const int globalLevel = 3;
bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels
bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals
bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals
static bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels
static bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals
static bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals
public:
bool isEmpty() { return table.size() == 0; }
bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); }
bool atGlobalLevel() { return isGlobalLevel(currentLevel()); }
static bool isBuiltInSymbol(long long uniqueId) {
int level = static_cast<int>(uniqueId >> LevelFlagBitOffset);
return isBuiltInLevel(level);
}
static constexpr uint64_t uniqueIdMask = (1LL << LevelFlagBitOffset) - 1;
static const uint32_t MaxLevelInUniqueID = 127;
void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; }
void setSeparateNameSpaces() { separateNameSpaces = true; }
void push()
{
table.push_back(new TSymbolTableLevel);
updateUniqueIdLevelFlag();
}
// Make a new symbol-table level to represent the scope introduced by a structure
@ -639,6 +678,7 @@ public:
{
assert(thisSymbol.getName().size() == 0);
table.push_back(new TSymbolTableLevel);
updateUniqueIdLevelFlag();
table.back()->setThisLevel();
insert(thisSymbol);
}
@ -648,6 +688,7 @@ public:
table[currentLevel()]->getPreviousDefaultPrecisions(p);
delete table.back();
table.pop_back();
updateUniqueIdLevelFlag();
}
//
@ -685,6 +726,16 @@ public:
return table[currentLevel()]->amend(symbol, firstNewMember);
}
// Update the level info in symbol's unique ID to current level
void amendSymbolIdLevel(TSymbol& symbol)
{
// clamp level to avoid overflow
uint64_t level = (uint32_t)currentLevel() > MaxLevelInUniqueID ? MaxLevelInUniqueID : currentLevel();
uint64_t symbolId = symbol.getUniqueId();
symbolId &= uniqueIdMask;
symbolId |= (level << LevelFlagBitOffset);
symbol.setUniqueId(symbolId);
}
//
// To allocate an internal temporary, which will need to be uniquely
// identified by the consumer of the AST, but never need to
@ -756,6 +807,12 @@ public:
return symbol;
}
void retargetSymbol(const TString& from, const TString& to) {
int level = currentLevel();
table[level]->retargetSymbol(from, to);
}
// Find of a symbol that returns how many layers deep of nested
// structures-with-member-functions ('this' scopes) deep the symbol was
// found in.
@ -853,8 +910,8 @@ public:
}
}
int getMaxSymbolId() { return uniqueId; }
#ifndef GLSLANG_WEB
long long getMaxSymbolId() { return uniqueId; }
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
void dump(TInfoSink& infoSink, bool complete = false) const;
#endif
void copyTable(const TSymbolTable& copyOf);
@ -867,14 +924,27 @@ public:
table[level]->readOnly();
}
// Add current level in the high-bits of unique id
void updateUniqueIdLevelFlag() {
// clamp level to avoid overflow
uint64_t level = (uint32_t)currentLevel() > MaxLevelInUniqueID ? MaxLevelInUniqueID : currentLevel();
uniqueId &= uniqueIdMask;
uniqueId |= (level << LevelFlagBitOffset);
}
void overwriteUniqueId(long long id)
{
uniqueId = id;
updateUniqueIdLevelFlag();
}
protected:
TSymbolTable(TSymbolTable&);
TSymbolTable& operator=(TSymbolTableLevel&);
int currentLevel() const { return static_cast<int>(table.size()) - 1; }
std::vector<TSymbolTableLevel*> table;
int uniqueId; // for unique identification in code generation
long long uniqueId; // for unique identification in code generation
bool noBuiltInRedeclarations;
bool separateNameSpaces;
unsigned int adoptedLevels;

View file

@ -2,7 +2,8 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2015-2020 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@ -63,6 +64,7 @@
// checkDeprecated()
// requireNotRemoved()
// requireExtensions()
// extensionRequires()
//
// Typically, only the first two calls are needed. They go into a code path that
// implements Feature F, and will log the proper error/warning messages. Parsing
@ -77,9 +79,11 @@
// const char* const XXX_extension_X = "XXX_extension_X";
//
// 2) Add extension initialization to TParseVersions::initializeExtensionBehavior(),
// the first function below:
// the first function below and optionally a entry to extensionData for additional
// error checks:
//
// extensionBehavior[XXX_extension_X] = EBhDisable;
// (Optional) exts[] = {XXX_extension_X, EShTargetSpv_1_4}
//
// 3) Add any preprocessor directives etc. in the next function, TParseVersions::getPreamble():
//
@ -139,6 +143,8 @@
// set of extensions that both enable them and are necessary, given the version of the symbol
// table. (There is a different symbol table for each version.)
//
// 7) If the extension has additional requirements like minimum SPIR-V version required, add them
// to extensionRequires()
#include "parseVersions.h"
#include "localintermediate.h"
@ -154,6 +160,22 @@ namespace glslang {
//
void TParseVersions::initializeExtensionBehavior()
{
typedef struct {
const char *const extensionName;
EShTargetLanguageVersion minSpvVersion;
} extensionData;
const extensionData exts[] = { {E_GL_EXT_ray_tracing, EShTargetSpv_1_4},
{E_GL_NV_ray_tracing_motion_blur, EShTargetSpv_1_4}
};
for (size_t ii = 0; ii < sizeof(exts) / sizeof(exts[0]); ii++) {
// Add only extensions which require > spv1.0 to save space in map
if (exts[ii].minSpvVersion > EShTargetSpv_1_0) {
extensionMinSpv[exts[ii].extensionName] = exts[ii].minSpvVersion;
}
}
extensionBehavior[E_GL_OES_texture_3D] = EBhDisable;
extensionBehavior[E_GL_OES_standard_derivatives] = EBhDisable;
extensionBehavior[E_GL_EXT_frag_depth] = EBhDisable;
@ -178,12 +200,14 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_ARB_explicit_uniform_location] = EBhDisable;
extensionBehavior[E_GL_ARB_shader_image_load_store] = EBhDisable;
extensionBehavior[E_GL_ARB_shader_atomic_counters] = EBhDisable;
extensionBehavior[E_GL_ARB_shader_atomic_counter_ops] = EBhDisable;
extensionBehavior[E_GL_ARB_shader_draw_parameters] = EBhDisable;
extensionBehavior[E_GL_ARB_shader_group_vote] = EBhDisable;
extensionBehavior[E_GL_ARB_derivative_control] = EBhDisable;
extensionBehavior[E_GL_ARB_shader_texture_image_samples] = EBhDisable;
extensionBehavior[E_GL_ARB_viewport_array] = EBhDisable;
extensionBehavior[E_GL_ARB_gpu_shader_int64] = EBhDisable;
extensionBehavior[E_GL_ARB_gpu_shader_fp64] = EBhDisable;
extensionBehavior[E_GL_ARB_shader_ballot] = EBhDisable;
extensionBehavior[E_GL_ARB_sparse_texture2] = EBhDisable;
extensionBehavior[E_GL_ARB_sparse_texture_clamp] = EBhDisable;
@ -195,6 +219,15 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_ARB_shader_clock] = EBhDisable;
extensionBehavior[E_GL_ARB_uniform_buffer_object] = EBhDisable;
extensionBehavior[E_GL_ARB_sample_shading] = EBhDisable;
extensionBehavior[E_GL_ARB_shader_bit_encoding] = EBhDisable;
extensionBehavior[E_GL_ARB_shader_image_size] = EBhDisable;
extensionBehavior[E_GL_ARB_shader_storage_buffer_object] = EBhDisable;
extensionBehavior[E_GL_ARB_shading_language_packing] = EBhDisable;
extensionBehavior[E_GL_ARB_texture_query_lod] = EBhDisable;
extensionBehavior[E_GL_ARB_vertex_attrib_64bit] = EBhDisable;
extensionBehavior[E_GL_ARB_draw_instanced] = EBhDisable;
extensionBehavior[E_GL_ARB_fragment_coord_conventions] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_basic] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_vote] = EBhDisable;
@ -220,9 +253,13 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_buffer_reference2] = EBhDisable;
extensionBehavior[E_GL_EXT_buffer_reference_uvec2] = EBhDisable;
extensionBehavior[E_GL_EXT_demote_to_helper_invocation] = EBhDisable;
extensionBehavior[E_GL_EXT_debug_printf] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_16bit_storage] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_8bit_storage] = EBhDisable;
extensionBehavior[E_GL_EXT_subgroup_uniform_control_flow] = EBhDisable;
extensionBehavior[E_GL_EXT_fragment_shader_barycentric] = EBhDisable;
// #line and #include
extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive] = EBhDisable;
@ -252,6 +289,7 @@ void TParseVersions::initializeExtensionBehavior()
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_ray_tracing_motion_blur] = 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;
@ -277,6 +315,7 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_tessellation_point_size] = EBhDisable;
extensionBehavior[E_GL_EXT_texture_buffer] = EBhDisable;
extensionBehavior[E_GL_EXT_texture_cube_map_array] = EBhDisable;
extensionBehavior[E_GL_EXT_null_initializer] = EBhDisable;
// OES matching AEP
extensionBehavior[E_GL_OES_geometry_shader] = EBhDisable;
@ -288,11 +327,23 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_OES_tessellation_point_size] = EBhDisable;
extensionBehavior[E_GL_OES_texture_buffer] = EBhDisable;
extensionBehavior[E_GL_OES_texture_cube_map_array] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_integer_mix] = EBhDisable;
// EXT extensions
extensionBehavior[E_GL_EXT_device_group] = EBhDisable;
extensionBehavior[E_GL_EXT_multiview] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_realtime_clock] = EBhDisable;
extensionBehavior[E_GL_EXT_device_group] = EBhDisable;
extensionBehavior[E_GL_EXT_multiview] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_realtime_clock] = EBhDisable;
extensionBehavior[E_GL_EXT_ray_tracing] = EBhDisable;
extensionBehavior[E_GL_EXT_ray_query] = EBhDisable;
extensionBehavior[E_GL_EXT_ray_flags_primitive_culling] = EBhDisable;
extensionBehavior[E_GL_EXT_ray_cull_mask] = EBhDisable;
extensionBehavior[E_GL_EXT_blend_func_extended] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_implicit_conversions] = EBhDisable;
extensionBehavior[E_GL_EXT_fragment_shading_rate] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_image_int64] = EBhDisable;
extensionBehavior[E_GL_EXT_terminate_invocation] = EBhDisable;
extensionBehavior[E_GL_EXT_shared_memory_block] = EBhDisable;
extensionBehavior[E_GL_EXT_spirv_intrinsics] = EBhDisable;
// OVR extensions
extensionBehavior[E_GL_OVR_multiview] = EBhDisable;
@ -313,7 +364,10 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_int16] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_int64] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_float16] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_atomic_float] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_atomic_float2] = EBhDisable;
}
#endif // GLSLANG_WEB
// Get code that is not part of a shared symbol table, is specific to this shader,
@ -335,10 +389,10 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_YUV_target 1\n"
"#define GL_EXT_shader_texture_lod 1\n"
"#define GL_EXT_shadow_samplers 1\n"
"#define GL_EXT_fragment_shading_rate 1\n"
// AEP
"#define GL_ANDROID_extension_pack_es31a 1\n"
"#define GL_KHR_blend_equation_advanced 1\n"
"#define GL_OES_sample_variables 1\n"
"#define GL_OES_shader_image_atomic 1\n"
"#define GL_OES_shader_multisample_interpolation 1\n"
@ -352,6 +406,9 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_tessellation_point_size 1\n"
"#define GL_EXT_texture_buffer 1\n"
"#define GL_EXT_texture_cube_map_array 1\n"
"#define GL_EXT_shader_implicit_conversions 1\n"
"#define GL_EXT_shader_integer_mix 1\n"
"#define GL_EXT_blend_func_extended 1\n"
// OES matching AEP
"#define GL_OES_geometry_shader 1\n"
@ -366,11 +423,15 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_shader_non_constant_global_initializers 1\n"
;
if (isEsProfile() && version >= 300) {
if (version >= 300) {
preamble += "#define GL_NV_shader_noperspective_interpolation 1\n";
}
if (version >= 310) {
preamble += "#define GL_EXT_null_initializer 1\n";
preamble += "#define GL_EXT_subgroup_uniform_control_flow 1\n";
}
} else {
} else { // !isEsProfile()
preamble =
"#define GL_FRAGMENT_PRECISION_HIGH 1\n"
"#define GL_ARB_texture_rectangle 1\n"
@ -394,15 +455,24 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_ARB_shader_texture_image_samples 1\n"
"#define GL_ARB_viewport_array 1\n"
"#define GL_ARB_gpu_shader_int64 1\n"
"#define GL_ARB_gpu_shader_fp64 1\n"
"#define GL_ARB_shader_ballot 1\n"
"#define GL_ARB_sparse_texture2 1\n"
"#define GL_ARB_sparse_texture_clamp 1\n"
"#define GL_ARB_shader_stencil_export 1\n"
"#define GL_ARB_sample_shading 1\n"
"#define GL_ARB_shader_image_size 1\n"
"#define GL_ARB_shading_language_packing 1\n"
// "#define GL_ARB_cull_distance 1\n" // present for 4.5, but need extension control over block members
"#define GL_ARB_post_depth_coverage 1\n"
"#define GL_ARB_fragment_shader_interlock 1\n"
"#define GL_ARB_uniform_buffer_object 1\n"
"#define GL_ARB_shader_bit_encoding 1\n"
"#define GL_ARB_shader_storage_buffer_object 1\n"
"#define GL_ARB_texture_query_lod 1\n"
"#define GL_ARB_vertex_attrib_64bit 1\n"
"#define GL_ARB_draw_instanced 1\n"
"#define GL_ARB_fragment_coord_conventions 1\n"
"#define GL_EXT_shader_non_constant_global_initializers 1\n"
"#define GL_EXT_shader_image_load_formatted 1\n"
"#define GL_EXT_post_depth_coverage 1\n"
@ -417,6 +487,10 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_buffer_reference2 1\n"
"#define GL_EXT_buffer_reference_uvec2 1\n"
"#define GL_EXT_demote_to_helper_invocation 1\n"
"#define GL_EXT_debug_printf 1\n"
"#define GL_EXT_fragment_shading_rate 1\n"
"#define GL_EXT_shared_memory_block 1\n"
"#define GL_EXT_shader_integer_mix 1\n"
// GL_KHR_shader_subgroup
"#define GL_KHR_shader_subgroup_basic 1\n"
@ -428,8 +502,14 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_KHR_shader_subgroup_clustered 1\n"
"#define GL_KHR_shader_subgroup_quad 1\n"
"#define E_GL_EXT_shader_atomic_int64 1\n"
"#define E_GL_EXT_shader_realtime_clock 1\n"
"#define GL_EXT_shader_image_int64 1\n"
"#define GL_EXT_shader_atomic_int64 1\n"
"#define GL_EXT_shader_realtime_clock 1\n"
"#define GL_EXT_ray_tracing 1\n"
"#define GL_EXT_ray_query 1\n"
"#define GL_EXT_ray_flags_primitive_culling 1\n"
"#define GL_EXT_ray_cull_mask 1\n"
"#define GL_EXT_spirv_intrinsics 1\n"
"#define GL_AMD_shader_ballot 1\n"
"#define GL_AMD_shader_trinary_minmax 1\n"
@ -452,6 +532,7 @@ void TParseVersions::getPreamble(std::string& preamble)
"#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_ray_tracing_motion_blur 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"
@ -472,6 +553,11 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_shader_subgroup_extended_types_int16 1\n"
"#define GL_EXT_shader_subgroup_extended_types_int64 1\n"
"#define GL_EXT_shader_subgroup_extended_types_float16 1\n"
"#define GL_EXT_shader_atomic_float 1\n"
"#define GL_EXT_shader_atomic_float2 1\n"
"#define GL_EXT_fragment_shader_barycentric 1\n"
;
if (version >= 150) {
@ -481,6 +567,10 @@ void TParseVersions::getPreamble(std::string& preamble)
if (profile == ECompatibilityProfile)
preamble += "#define GL_compatibility_profile 1\n";
}
if (version >= 140) {
preamble += "#define GL_EXT_null_initializer 1\n";
preamble += "#define GL_EXT_subgroup_uniform_control_flow 1\n";
}
#endif // GLSLANG_WEB
}
@ -505,6 +595,12 @@ void TParseVersions::getPreamble(std::string& preamble)
preamble +=
"#define GL_GOOGLE_cpp_style_line_directive 1\n"
"#define GL_GOOGLE_include_directive 1\n"
"#define GL_KHR_blend_equation_advanced 1\n"
;
// other general extensions
preamble +=
"#define GL_EXT_terminate_invocation 1\n"
;
#endif
@ -527,6 +623,29 @@ void TParseVersions::getPreamble(std::string& preamble)
preamble += "\n";
}
#endif
#ifndef GLSLANG_WEB
// GL_EXT_spirv_intrinsics
if (!isEsProfile()) {
switch (language) {
case EShLangVertex: preamble += "#define GL_VERTEX_SHADER 1 \n"; break;
case EShLangTessControl: preamble += "#define GL_TESSELLATION_CONTROL_SHADER 1 \n"; break;
case EShLangTessEvaluation: preamble += "#define GL_TESSELLATION_EVALUATION_SHADER 1 \n"; break;
case EShLangGeometry: preamble += "#define GL_GEOMETRY_SHADER 1 \n"; break;
case EShLangFragment: preamble += "#define GL_FRAGMENT_SHADER 1 \n"; break;
case EShLangCompute: preamble += "#define GL_COMPUTE_SHADER 1 \n"; break;
case EShLangRayGen: preamble += "#define GL_RAY_GENERATION_SHADER_EXT 1 \n"; break;
case EShLangIntersect: preamble += "#define GL_INTERSECTION_SHADER_EXT 1 \n"; break;
case EShLangAnyHit: preamble += "#define GL_ANY_HIT_SHADER_EXT 1 \n"; break;
case EShLangClosestHit: preamble += "#define GL_CLOSEST_HIT_SHADER_EXT 1 \n"; break;
case EShLangMiss: preamble += "#define GL_MISS_SHADER_EXT 1 \n"; break;
case EShLangCallable: preamble += "#define GL_CALLABLE_SHADER_EXT 1 \n"; break;
case EShLangTaskNV: preamble += "#define GL_TASK_SHADER_NV 1 \n"; break;
case EShLangMeshNV: preamble += "#define GL_MESH_SHADER_NV 1 \n"; break;
default: break;
}
}
#endif
}
//
@ -542,12 +661,12 @@ const char* StageName(EShLanguage stage)
case EShLangTessControl: return "tessellation control";
case EShLangTessEvaluation: return "tessellation evaluation";
case EShLangGeometry: return "geometry";
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 EShLangRayGen: return "ray-generation";
case EShLangIntersect: return "intersection";
case EShLangAnyHit: return "any-hit";
case EShLangClosestHit: return "closest-hit";
case EShLangMiss: return "miss";
case EShLangCallable: return "callable";
case EShLangMeshNV: return "mesh";
case EShLangTaskNV: return "task";
#endif
@ -710,7 +829,8 @@ bool TParseVersions::checkExtensionsRequested(const TSourceLoc& loc, int numExte
// Use when there are no profile/version to check, it's just an error if one of the
// extensions is not present.
//
void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[],
const char* featureDesc)
{
if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc))
return;
@ -729,7 +849,8 @@ void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions,
// Use by preprocessor when there are no profile/version to check, it's just an error if one of the
// extensions is not present.
//
void TParseVersions::ppRequireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
void TParseVersions::ppRequireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[],
const char* featureDesc)
{
if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc))
return;
@ -795,10 +916,14 @@ void TParseVersions::updateExtensionBehavior(int line, const char* extension, co
error(getCurrentLoc(), "behavior not supported:", "#extension", behaviorString);
return;
}
bool on = behavior != EBhDisable;
// check if extension is used with correct shader stage
checkExtensionStage(getCurrentLoc(), extension);
// check if extension has additional requirements
extensionRequires(getCurrentLoc(), extension, behaviorString);
// update the requested extension
updateExtensionBehavior(extension, behavior);
@ -861,6 +986,32 @@ void TParseVersions::updateExtensionBehavior(int line, const char* extension, co
updateExtensionBehavior(line, "GL_EXT_shader_explicit_arithmetic_types_int64", behaviorString);
else if (strcmp(extension, "GL_EXT_shader_subgroup_extended_types_float16") == 0)
updateExtensionBehavior(line, "GL_EXT_shader_explicit_arithmetic_types_float16", behaviorString);
// see if we need to update the numeric features
else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types") == 0)
intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types, on);
else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int8") == 0)
intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int8, on);
else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int16") == 0)
intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int16, on);
else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int32") == 0)
intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int32, on);
else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int64") == 0)
intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int64, on);
else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_float16") == 0)
intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_float16, on);
else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_float32") == 0)
intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_float32, on);
else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_float64") == 0)
intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_float64, on);
else if (strcmp(extension, "GL_EXT_shader_implicit_conversions") == 0)
intermediate.updateNumericFeature(TNumericFeatures::shader_implicit_conversions, on);
else if (strcmp(extension, "GL_ARB_gpu_shader_fp64") == 0)
intermediate.updateNumericFeature(TNumericFeatures::gpu_shader_fp64, on);
else if (strcmp(extension, "GL_AMD_gpu_shader_int16") == 0)
intermediate.updateNumericFeature(TNumericFeatures::gpu_shader_int16, on);
else if (strcmp(extension, "GL_AMD_gpu_shader_half_float") == 0)
intermediate.updateNumericFeature(TNumericFeatures::gpu_shader_half_float, on);
}
void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBehavior behavior)
@ -896,7 +1047,7 @@ void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBe
} else {
if (iter->second == EBhDisablePartial)
warn(getCurrentLoc(), "extension is only partially supported:", "#extension", extension);
if (behavior == EBhEnable || behavior == EBhRequire)
if (behavior != EBhDisable)
intermediate.addRequestedExtension(extension);
iter->second = behavior;
}
@ -915,6 +1066,24 @@ void TParseVersions::checkExtensionStage(const TSourceLoc& loc, const char * con
}
}
// Check if extension has additional requirements
void TParseVersions::extensionRequires(const TSourceLoc &loc, const char * const extension, const char *behaviorString)
{
bool isEnabled = false;
if (!strcmp("require", behaviorString))
isEnabled = true;
else if (!strcmp("enable", behaviorString))
isEnabled = true;
if (isEnabled) {
unsigned int minSpvVersion = 0;
auto iter = extensionMinSpv.find(TString(extension));
if (iter != extensionMinSpv.end())
minSpvVersion = iter->second;
requireSpv(loc, extension, minSpvVersion);
}
}
// Call for any operation needing full GLSL integer data-type support.
void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op)
{
@ -925,8 +1094,13 @@ void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op)
// Call for any operation needing GLSL double data-type support.
void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op)
{
requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, nullptr, op);
//requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
if (language == EShLangVertex) {
const char* const f64_Extensions[] = {E_GL_ARB_gpu_shader_fp64, E_GL_ARB_vertex_attrib_64bit};
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, 2, f64_Extensions, op);
} else
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader_fp64, op);
}
// Call for any operation needing GLSL float16 data-type support.
@ -1146,7 +1320,7 @@ void TParseVersions::spvRemoved(const TSourceLoc& loc, const char* op)
// Call for any operation removed because Vulkan SPIR-V is being generated.
void TParseVersions::vulkanRemoved(const TSourceLoc& loc, const char* op)
{
if (spvVersion.vulkan > 0)
if (spvVersion.vulkan > 0 && !spvVersion.vulkanRelaxed)
error(loc, "not allowed when using GLSL for Vulkan", op, "");
}
@ -1167,5 +1341,12 @@ void TParseVersions::requireSpv(const TSourceLoc& loc, const char* op)
error(loc, "only allowed when generating SPIR-V", op, "");
#endif
}
void TParseVersions::requireSpv(const TSourceLoc& loc, const char *op, unsigned int version)
{
#ifndef GLSLANG_WEB
if (spvVersion.spv < version)
error(loc, "not supported for current targeted SPIR-V version", op, "");
#endif
}
} // end namespace glslang

View file

@ -3,6 +3,7 @@
// Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@ -35,9 +36,12 @@
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#ifndef _VERSIONS_INCLUDED_
#define _VERSIONS_INCLUDED_
#define LAST_ELEMENT_MARKER(x) x
//
// Help manage multiple profiles, versions, extensions etc.
//
@ -49,12 +53,13 @@
// Don't maintain an ordinal set of enums (0,1,2,3...) to avoid all possible
// defects from mixing the two different forms.
//
typedef enum {
typedef enum : unsigned {
EBadProfile = 0,
ENoProfile = (1 << 0), // only for desktop, before profiles showed up
ECoreProfile = (1 << 1),
ECompatibilityProfile = (1 << 2),
EEsProfile = (1 << 3)
EEsProfile = (1 << 3),
LAST_ELEMENT_MARKER(EProfileCount),
} EProfile;
namespace glslang {
@ -82,11 +87,12 @@ inline const char* ProfileName(EProfile profile)
// The union of all requested rule sets will be applied.
//
struct SpvVersion {
SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0) {}
SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0), vulkanRelaxed(false) {}
unsigned int spv; // the version of SPIR-V to target, as defined by "word 1" of the SPIR-V binary header
int vulkanGlsl; // the version of GLSL semantics for Vulkan, from GL_KHR_vulkan_glsl, for "#define VULKAN XXX"
int vulkan; // the version of Vulkan, for which SPIR-V execution environment rules to use
int openGl; // the version of GLSL semantics for OpenGL, from GL_ARB_gl_spirv, for "#define GL_SPIRV XXX"
bool vulkanRelaxed; // relax changes to GLSL for Vulkan, allowing some GL-specific to be compiled to Vulkan SPIR-V target
};
//
@ -130,12 +136,14 @@ const char* const E_GL_ARB_explicit_attrib_location = "GL_ARB_explicit_attri
const char* const E_GL_ARB_explicit_uniform_location = "GL_ARB_explicit_uniform_location";
const char* const E_GL_ARB_shader_image_load_store = "GL_ARB_shader_image_load_store";
const char* const E_GL_ARB_shader_atomic_counters = "GL_ARB_shader_atomic_counters";
const char* const E_GL_ARB_shader_atomic_counter_ops = "GL_ARB_shader_atomic_counter_ops";
const char* const E_GL_ARB_shader_draw_parameters = "GL_ARB_shader_draw_parameters";
const char* const E_GL_ARB_shader_group_vote = "GL_ARB_shader_group_vote";
const char* const E_GL_ARB_derivative_control = "GL_ARB_derivative_control";
const char* const E_GL_ARB_shader_texture_image_samples = "GL_ARB_shader_texture_image_samples";
const char* const E_GL_ARB_viewport_array = "GL_ARB_viewport_array";
const char* const E_GL_ARB_gpu_shader_int64 = "GL_ARB_gpu_shader_int64";
const char* const E_GL_ARB_gpu_shader_fp64 = "GL_ARB_gpu_shader_fp64";
const char* const E_GL_ARB_shader_ballot = "GL_ARB_shader_ballot";
const char* const E_GL_ARB_sparse_texture2 = "GL_ARB_sparse_texture2";
const char* const E_GL_ARB_sparse_texture_clamp = "GL_ARB_sparse_texture_clamp";
@ -147,6 +155,14 @@ const char* const E_GL_ARB_fragment_shader_interlock = "GL_ARB_fragment_shade
const char* const E_GL_ARB_shader_clock = "GL_ARB_shader_clock";
const char* const E_GL_ARB_uniform_buffer_object = "GL_ARB_uniform_buffer_object";
const char* const E_GL_ARB_sample_shading = "GL_ARB_sample_shading";
const char* const E_GL_ARB_shader_bit_encoding = "GL_ARB_shader_bit_encoding";
const char* const E_GL_ARB_shader_image_size = "GL_ARB_shader_image_size";
const char* const E_GL_ARB_shader_storage_buffer_object = "GL_ARB_shader_storage_buffer_object";
const char* const E_GL_ARB_shading_language_packing = "GL_ARB_shading_language_packing";
const char* const E_GL_ARB_texture_query_lod = "GL_ARB_texture_query_lod";
const char* const E_GL_ARB_vertex_attrib_64bit = "GL_ARB_vertex_attrib_64bit";
const char* const E_GL_ARB_draw_instanced = "GL_ARB_draw_instanced";
const char* const E_GL_ARB_fragment_coord_conventions = "GL_ARB_fragment_coord_conventions";
const char* const E_GL_KHR_shader_subgroup_basic = "GL_KHR_shader_subgroup_basic";
const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote";
@ -181,6 +197,20 @@ const char* const E_GL_EXT_buffer_reference2 = "GL_EXT_buffer_ref
const char* const E_GL_EXT_buffer_reference_uvec2 = "GL_EXT_buffer_reference_uvec2";
const char* const E_GL_EXT_demote_to_helper_invocation = "GL_EXT_demote_to_helper_invocation";
const char* const E_GL_EXT_shader_realtime_clock = "GL_EXT_shader_realtime_clock";
const char* const E_GL_EXT_debug_printf = "GL_EXT_debug_printf";
const char* const E_GL_EXT_ray_tracing = "GL_EXT_ray_tracing";
const char* const E_GL_EXT_ray_query = "GL_EXT_ray_query";
const char* const E_GL_EXT_ray_flags_primitive_culling = "GL_EXT_ray_flags_primitive_culling";
const char* const E_GL_EXT_ray_cull_mask = "GL_EXT_ray_cull_mask";
const char* const E_GL_EXT_blend_func_extended = "GL_EXT_blend_func_extended";
const char* const E_GL_EXT_shader_implicit_conversions = "GL_EXT_shader_implicit_conversions";
const char* const E_GL_EXT_fragment_shading_rate = "GL_EXT_fragment_shading_rate";
const char* const E_GL_EXT_shader_image_int64 = "GL_EXT_shader_image_int64";
const char* const E_GL_EXT_null_initializer = "GL_EXT_null_initializer";
const char* const E_GL_EXT_shared_memory_block = "GL_EXT_shared_memory_block";
const char* const E_GL_EXT_subgroup_uniform_control_flow = "GL_EXT_subgroup_uniform_control_flow";
const char* const E_GL_EXT_spirv_intrinsics = "GL_EXT_spirv_intrinsics";
const char* const E_GL_EXT_fragment_shader_barycentric = "GL_EXT_fragment_shader_barycentric";
// Arrays of extensions for the above viewportEXTs duplications
@ -222,6 +252,7 @@ const char* const E_GL_NV_shader_noperspective_interpolation = "GL_NV_shader_
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_ray_tracing_motion_blur = "GL_NV_ray_tracing_motion_blur";
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";
@ -252,6 +283,7 @@ const char* const E_GL_EXT_tessellation_shader = "GL_EXT_tessel
const char* const E_GL_EXT_tessellation_point_size = "GL_EXT_tessellation_point_size";
const char* const E_GL_EXT_texture_buffer = "GL_EXT_texture_buffer";
const char* const E_GL_EXT_texture_cube_map_array = "GL_EXT_texture_cube_map_array";
const char* const E_GL_EXT_shader_integer_mix = "GL_EXT_shader_integer_mix";
// OES matching AEP
const char* const E_GL_OES_geometry_shader = "GL_OES_geometry_shader";
@ -278,6 +310,10 @@ const char* const E_GL_EXT_shader_subgroup_extended_types_int8 = "GL_EXT_shad
const char* const E_GL_EXT_shader_subgroup_extended_types_int16 = "GL_EXT_shader_subgroup_extended_types_int16";
const char* const E_GL_EXT_shader_subgroup_extended_types_int64 = "GL_EXT_shader_subgroup_extended_types_int64";
const char* const E_GL_EXT_shader_subgroup_extended_types_float16 = "GL_EXT_shader_subgroup_extended_types_float16";
const char* const E_GL_EXT_terminate_invocation = "GL_EXT_terminate_invocation";
const char* const E_GL_EXT_shader_atomic_float = "GL_EXT_shader_atomic_float";
const char* const E_GL_EXT_shader_atomic_float2 = "GL_EXT_shader_atomic_float2";
// Arrays of extensions for the above AEP duplications

View file

@ -123,6 +123,8 @@ TAttributeType TParseContext::attributeFromName(const TString& name) const
return EatPeelCount;
else if (name == "partial_count")
return EatPartialCount;
else if (name == "subgroup_uniform_control_flow")
return EatSubgroupUniformControlFlow;
else
return EatNone;
}
@ -341,6 +343,29 @@ void TParseContext::handleLoopAttributes(const TAttributes& attributes, TIntermN
}
}
//
// Function attributes
//
void TParseContext::handleFunctionAttributes(const TSourceLoc& loc, const TAttributes& attributes)
{
for (auto it = attributes.begin(); it != attributes.end(); ++it) {
if (it->size() > 0) {
warn(loc, "attribute with arguments not recognized, skipping", "", "");
continue;
}
switch (it->name) {
case EatSubgroupUniformControlFlow:
intermediate.setSubgroupUniformControlFlow();
break;
default:
warn(loc, "attribute does not apply to a function", "", "");
break;
}
}
}
} // end namespace glslang
#endif // GLSLANG_WEB

View file

@ -118,7 +118,8 @@ namespace glslang {
EatFormatR8ui,
EatFormatUnknown,
EatNonWritable,
EatNonReadable
EatNonReadable,
EatSubgroupUniformControlFlow,
};
class TIntermAggregate;

View file

@ -49,9 +49,17 @@
#define GL_INT64_VEC4_ARB 0x8FEB
#define GL_UNSIGNED_INT64_ARB 0x140F
#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FE5
#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FE6
#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FE7
#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FF5
#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FF6
#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FF7
#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1
#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2
#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3
#define GL_INT16_NV 0x8FE4
#define GL_INT16_VEC2_NV 0x8FE5
#define GL_INT16_VEC3_NV 0x8FE6
#define GL_INT16_VEC4_NV 0x8FE7
#define GL_BOOL 0x8B56
#define GL_BOOL_VEC2 0x8B57

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,9 @@
/* A Bison parser, made by GNU Bison 3.0.4. */
/* A Bison parser, made by GNU Bison 3.7.4. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
Inc.
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
@ -30,6 +31,10 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
especially those whose name start with YY_ or yy_. They are
private implementation details that can be changed or removed. */
#ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
/* Debug traces. */
@ -40,428 +45,477 @@
extern int yydebug;
#endif
/* Token type. */
/* Token kinds. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
enum yytokentype
{
CONST = 258,
BOOL = 259,
INT = 260,
UINT = 261,
FLOAT = 262,
BVEC2 = 263,
BVEC3 = 264,
BVEC4 = 265,
IVEC2 = 266,
IVEC3 = 267,
IVEC4 = 268,
UVEC2 = 269,
UVEC3 = 270,
UVEC4 = 271,
VEC2 = 272,
VEC3 = 273,
VEC4 = 274,
MAT2 = 275,
MAT3 = 276,
MAT4 = 277,
MAT2X2 = 278,
MAT2X3 = 279,
MAT2X4 = 280,
MAT3X2 = 281,
MAT3X3 = 282,
MAT3X4 = 283,
MAT4X2 = 284,
MAT4X3 = 285,
MAT4X4 = 286,
SAMPLER2D = 287,
SAMPLER3D = 288,
SAMPLERCUBE = 289,
SAMPLER2DSHADOW = 290,
SAMPLERCUBESHADOW = 291,
SAMPLER2DARRAY = 292,
SAMPLER2DARRAYSHADOW = 293,
ISAMPLER2D = 294,
ISAMPLER3D = 295,
ISAMPLERCUBE = 296,
ISAMPLER2DARRAY = 297,
USAMPLER2D = 298,
USAMPLER3D = 299,
USAMPLERCUBE = 300,
USAMPLER2DARRAY = 301,
SAMPLER = 302,
SAMPLERSHADOW = 303,
TEXTURE2D = 304,
TEXTURE3D = 305,
TEXTURECUBE = 306,
TEXTURE2DARRAY = 307,
ITEXTURE2D = 308,
ITEXTURE3D = 309,
ITEXTURECUBE = 310,
ITEXTURE2DARRAY = 311,
UTEXTURE2D = 312,
UTEXTURE3D = 313,
UTEXTURECUBE = 314,
UTEXTURE2DARRAY = 315,
ATTRIBUTE = 316,
VARYING = 317,
FLOAT16_T = 318,
FLOAT32_T = 319,
DOUBLE = 320,
FLOAT64_T = 321,
INT64_T = 322,
UINT64_T = 323,
INT32_T = 324,
UINT32_T = 325,
INT16_T = 326,
UINT16_T = 327,
INT8_T = 328,
UINT8_T = 329,
I64VEC2 = 330,
I64VEC3 = 331,
I64VEC4 = 332,
U64VEC2 = 333,
U64VEC3 = 334,
U64VEC4 = 335,
I32VEC2 = 336,
I32VEC3 = 337,
I32VEC4 = 338,
U32VEC2 = 339,
U32VEC3 = 340,
U32VEC4 = 341,
I16VEC2 = 342,
I16VEC3 = 343,
I16VEC4 = 344,
U16VEC2 = 345,
U16VEC3 = 346,
U16VEC4 = 347,
I8VEC2 = 348,
I8VEC3 = 349,
I8VEC4 = 350,
U8VEC2 = 351,
U8VEC3 = 352,
U8VEC4 = 353,
DVEC2 = 354,
DVEC3 = 355,
DVEC4 = 356,
DMAT2 = 357,
DMAT3 = 358,
DMAT4 = 359,
F16VEC2 = 360,
F16VEC3 = 361,
F16VEC4 = 362,
F16MAT2 = 363,
F16MAT3 = 364,
F16MAT4 = 365,
F32VEC2 = 366,
F32VEC3 = 367,
F32VEC4 = 368,
F32MAT2 = 369,
F32MAT3 = 370,
F32MAT4 = 371,
F64VEC2 = 372,
F64VEC3 = 373,
F64VEC4 = 374,
F64MAT2 = 375,
F64MAT3 = 376,
F64MAT4 = 377,
DMAT2X2 = 378,
DMAT2X3 = 379,
DMAT2X4 = 380,
DMAT3X2 = 381,
DMAT3X3 = 382,
DMAT3X4 = 383,
DMAT4X2 = 384,
DMAT4X3 = 385,
DMAT4X4 = 386,
F16MAT2X2 = 387,
F16MAT2X3 = 388,
F16MAT2X4 = 389,
F16MAT3X2 = 390,
F16MAT3X3 = 391,
F16MAT3X4 = 392,
F16MAT4X2 = 393,
F16MAT4X3 = 394,
F16MAT4X4 = 395,
F32MAT2X2 = 396,
F32MAT2X3 = 397,
F32MAT2X4 = 398,
F32MAT3X2 = 399,
F32MAT3X3 = 400,
F32MAT3X4 = 401,
F32MAT4X2 = 402,
F32MAT4X3 = 403,
F32MAT4X4 = 404,
F64MAT2X2 = 405,
F64MAT2X3 = 406,
F64MAT2X4 = 407,
F64MAT3X2 = 408,
F64MAT3X3 = 409,
F64MAT3X4 = 410,
F64MAT4X2 = 411,
F64MAT4X3 = 412,
F64MAT4X4 = 413,
ATOMIC_UINT = 414,
ACCSTRUCTNV = 415,
FCOOPMATNV = 416,
ICOOPMATNV = 417,
UCOOPMATNV = 418,
SAMPLERCUBEARRAY = 419,
SAMPLERCUBEARRAYSHADOW = 420,
ISAMPLERCUBEARRAY = 421,
USAMPLERCUBEARRAY = 422,
SAMPLER1D = 423,
SAMPLER1DARRAY = 424,
SAMPLER1DARRAYSHADOW = 425,
ISAMPLER1D = 426,
SAMPLER1DSHADOW = 427,
SAMPLER2DRECT = 428,
SAMPLER2DRECTSHADOW = 429,
ISAMPLER2DRECT = 430,
USAMPLER2DRECT = 431,
SAMPLERBUFFER = 432,
ISAMPLERBUFFER = 433,
USAMPLERBUFFER = 434,
SAMPLER2DMS = 435,
ISAMPLER2DMS = 436,
USAMPLER2DMS = 437,
SAMPLER2DMSARRAY = 438,
ISAMPLER2DMSARRAY = 439,
USAMPLER2DMSARRAY = 440,
SAMPLEREXTERNALOES = 441,
SAMPLEREXTERNAL2DY2YEXT = 442,
ISAMPLER1DARRAY = 443,
USAMPLER1D = 444,
USAMPLER1DARRAY = 445,
F16SAMPLER1D = 446,
F16SAMPLER2D = 447,
F16SAMPLER3D = 448,
F16SAMPLER2DRECT = 449,
F16SAMPLERCUBE = 450,
F16SAMPLER1DARRAY = 451,
F16SAMPLER2DARRAY = 452,
F16SAMPLERCUBEARRAY = 453,
F16SAMPLERBUFFER = 454,
F16SAMPLER2DMS = 455,
F16SAMPLER2DMSARRAY = 456,
F16SAMPLER1DSHADOW = 457,
F16SAMPLER2DSHADOW = 458,
F16SAMPLER1DARRAYSHADOW = 459,
F16SAMPLER2DARRAYSHADOW = 460,
F16SAMPLER2DRECTSHADOW = 461,
F16SAMPLERCUBESHADOW = 462,
F16SAMPLERCUBEARRAYSHADOW = 463,
IMAGE1D = 464,
IIMAGE1D = 465,
UIMAGE1D = 466,
IMAGE2D = 467,
IIMAGE2D = 468,
UIMAGE2D = 469,
IMAGE3D = 470,
IIMAGE3D = 471,
UIMAGE3D = 472,
IMAGE2DRECT = 473,
IIMAGE2DRECT = 474,
UIMAGE2DRECT = 475,
IMAGECUBE = 476,
IIMAGECUBE = 477,
UIMAGECUBE = 478,
IMAGEBUFFER = 479,
IIMAGEBUFFER = 480,
UIMAGEBUFFER = 481,
IMAGE1DARRAY = 482,
IIMAGE1DARRAY = 483,
UIMAGE1DARRAY = 484,
IMAGE2DARRAY = 485,
IIMAGE2DARRAY = 486,
UIMAGE2DARRAY = 487,
IMAGECUBEARRAY = 488,
IIMAGECUBEARRAY = 489,
UIMAGECUBEARRAY = 490,
IMAGE2DMS = 491,
IIMAGE2DMS = 492,
UIMAGE2DMS = 493,
IMAGE2DMSARRAY = 494,
IIMAGE2DMSARRAY = 495,
UIMAGE2DMSARRAY = 496,
F16IMAGE1D = 497,
F16IMAGE2D = 498,
F16IMAGE3D = 499,
F16IMAGE2DRECT = 500,
F16IMAGECUBE = 501,
F16IMAGE1DARRAY = 502,
F16IMAGE2DARRAY = 503,
F16IMAGECUBEARRAY = 504,
F16IMAGEBUFFER = 505,
F16IMAGE2DMS = 506,
F16IMAGE2DMSARRAY = 507,
TEXTURECUBEARRAY = 508,
ITEXTURECUBEARRAY = 509,
UTEXTURECUBEARRAY = 510,
TEXTURE1D = 511,
ITEXTURE1D = 512,
UTEXTURE1D = 513,
TEXTURE1DARRAY = 514,
ITEXTURE1DARRAY = 515,
UTEXTURE1DARRAY = 516,
TEXTURE2DRECT = 517,
ITEXTURE2DRECT = 518,
UTEXTURE2DRECT = 519,
TEXTUREBUFFER = 520,
ITEXTUREBUFFER = 521,
UTEXTUREBUFFER = 522,
TEXTURE2DMS = 523,
ITEXTURE2DMS = 524,
UTEXTURE2DMS = 525,
TEXTURE2DMSARRAY = 526,
ITEXTURE2DMSARRAY = 527,
UTEXTURE2DMSARRAY = 528,
F16TEXTURE1D = 529,
F16TEXTURE2D = 530,
F16TEXTURE3D = 531,
F16TEXTURE2DRECT = 532,
F16TEXTURECUBE = 533,
F16TEXTURE1DARRAY = 534,
F16TEXTURE2DARRAY = 535,
F16TEXTURECUBEARRAY = 536,
F16TEXTUREBUFFER = 537,
F16TEXTURE2DMS = 538,
F16TEXTURE2DMSARRAY = 539,
SUBPASSINPUT = 540,
SUBPASSINPUTMS = 541,
ISUBPASSINPUT = 542,
ISUBPASSINPUTMS = 543,
USUBPASSINPUT = 544,
USUBPASSINPUTMS = 545,
F16SUBPASSINPUT = 546,
F16SUBPASSINPUTMS = 547,
LEFT_OP = 548,
RIGHT_OP = 549,
INC_OP = 550,
DEC_OP = 551,
LE_OP = 552,
GE_OP = 553,
EQ_OP = 554,
NE_OP = 555,
AND_OP = 556,
OR_OP = 557,
XOR_OP = 558,
MUL_ASSIGN = 559,
DIV_ASSIGN = 560,
ADD_ASSIGN = 561,
MOD_ASSIGN = 562,
LEFT_ASSIGN = 563,
RIGHT_ASSIGN = 564,
AND_ASSIGN = 565,
XOR_ASSIGN = 566,
OR_ASSIGN = 567,
SUB_ASSIGN = 568,
LEFT_PAREN = 569,
RIGHT_PAREN = 570,
LEFT_BRACKET = 571,
RIGHT_BRACKET = 572,
LEFT_BRACE = 573,
RIGHT_BRACE = 574,
DOT = 575,
COMMA = 576,
COLON = 577,
EQUAL = 578,
SEMICOLON = 579,
BANG = 580,
DASH = 581,
TILDE = 582,
PLUS = 583,
STAR = 584,
SLASH = 585,
PERCENT = 586,
LEFT_ANGLE = 587,
RIGHT_ANGLE = 588,
VERTICAL_BAR = 589,
CARET = 590,
AMPERSAND = 591,
QUESTION = 592,
INVARIANT = 593,
HIGH_PRECISION = 594,
MEDIUM_PRECISION = 595,
LOW_PRECISION = 596,
PRECISION = 597,
PACKED = 598,
RESOURCE = 599,
SUPERP = 600,
FLOATCONSTANT = 601,
INTCONSTANT = 602,
UINTCONSTANT = 603,
BOOLCONSTANT = 604,
IDENTIFIER = 605,
TYPE_NAME = 606,
CENTROID = 607,
IN = 608,
OUT = 609,
INOUT = 610,
STRUCT = 611,
VOID = 612,
WHILE = 613,
BREAK = 614,
CONTINUE = 615,
DO = 616,
ELSE = 617,
FOR = 618,
IF = 619,
DISCARD = 620,
RETURN = 621,
SWITCH = 622,
CASE = 623,
DEFAULT = 624,
UNIFORM = 625,
SHARED = 626,
BUFFER = 627,
FLAT = 628,
SMOOTH = 629,
LAYOUT = 630,
DOUBLECONSTANT = 631,
INT16CONSTANT = 632,
UINT16CONSTANT = 633,
FLOAT16CONSTANT = 634,
INT32CONSTANT = 635,
UINT32CONSTANT = 636,
INT64CONSTANT = 637,
UINT64CONSTANT = 638,
SUBROUTINE = 639,
DEMOTE = 640,
PAYLOADNV = 641,
PAYLOADINNV = 642,
HITATTRNV = 643,
CALLDATANV = 644,
CALLDATAINNV = 645,
PATCH = 646,
SAMPLE = 647,
NONUNIFORM = 648,
COHERENT = 649,
VOLATILE = 650,
RESTRICT = 651,
READONLY = 652,
WRITEONLY = 653,
DEVICECOHERENT = 654,
QUEUEFAMILYCOHERENT = 655,
WORKGROUPCOHERENT = 656,
SUBGROUPCOHERENT = 657,
NONPRIVATE = 658,
NOPERSPECTIVE = 659,
EXPLICITINTERPAMD = 660,
PERVERTEXNV = 661,
PERPRIMITIVENV = 662,
PERVIEWNV = 663,
PERTASKNV = 664,
PRECISE = 665
YYEMPTY = -2,
YYEOF = 0, /* "end of file" */
YYerror = 256, /* error */
YYUNDEF = 257, /* "invalid token" */
CONST = 258, /* CONST */
BOOL = 259, /* BOOL */
INT = 260, /* INT */
UINT = 261, /* UINT */
FLOAT = 262, /* FLOAT */
BVEC2 = 263, /* BVEC2 */
BVEC3 = 264, /* BVEC3 */
BVEC4 = 265, /* BVEC4 */
IVEC2 = 266, /* IVEC2 */
IVEC3 = 267, /* IVEC3 */
IVEC4 = 268, /* IVEC4 */
UVEC2 = 269, /* UVEC2 */
UVEC3 = 270, /* UVEC3 */
UVEC4 = 271, /* UVEC4 */
VEC2 = 272, /* VEC2 */
VEC3 = 273, /* VEC3 */
VEC4 = 274, /* VEC4 */
MAT2 = 275, /* MAT2 */
MAT3 = 276, /* MAT3 */
MAT4 = 277, /* MAT4 */
MAT2X2 = 278, /* MAT2X2 */
MAT2X3 = 279, /* MAT2X3 */
MAT2X4 = 280, /* MAT2X4 */
MAT3X2 = 281, /* MAT3X2 */
MAT3X3 = 282, /* MAT3X3 */
MAT3X4 = 283, /* MAT3X4 */
MAT4X2 = 284, /* MAT4X2 */
MAT4X3 = 285, /* MAT4X3 */
MAT4X4 = 286, /* MAT4X4 */
SAMPLER2D = 287, /* SAMPLER2D */
SAMPLER3D = 288, /* SAMPLER3D */
SAMPLERCUBE = 289, /* SAMPLERCUBE */
SAMPLER2DSHADOW = 290, /* SAMPLER2DSHADOW */
SAMPLERCUBESHADOW = 291, /* SAMPLERCUBESHADOW */
SAMPLER2DARRAY = 292, /* SAMPLER2DARRAY */
SAMPLER2DARRAYSHADOW = 293, /* SAMPLER2DARRAYSHADOW */
ISAMPLER2D = 294, /* ISAMPLER2D */
ISAMPLER3D = 295, /* ISAMPLER3D */
ISAMPLERCUBE = 296, /* ISAMPLERCUBE */
ISAMPLER2DARRAY = 297, /* ISAMPLER2DARRAY */
USAMPLER2D = 298, /* USAMPLER2D */
USAMPLER3D = 299, /* USAMPLER3D */
USAMPLERCUBE = 300, /* USAMPLERCUBE */
USAMPLER2DARRAY = 301, /* USAMPLER2DARRAY */
SAMPLER = 302, /* SAMPLER */
SAMPLERSHADOW = 303, /* SAMPLERSHADOW */
TEXTURE2D = 304, /* TEXTURE2D */
TEXTURE3D = 305, /* TEXTURE3D */
TEXTURECUBE = 306, /* TEXTURECUBE */
TEXTURE2DARRAY = 307, /* TEXTURE2DARRAY */
ITEXTURE2D = 308, /* ITEXTURE2D */
ITEXTURE3D = 309, /* ITEXTURE3D */
ITEXTURECUBE = 310, /* ITEXTURECUBE */
ITEXTURE2DARRAY = 311, /* ITEXTURE2DARRAY */
UTEXTURE2D = 312, /* UTEXTURE2D */
UTEXTURE3D = 313, /* UTEXTURE3D */
UTEXTURECUBE = 314, /* UTEXTURECUBE */
UTEXTURE2DARRAY = 315, /* UTEXTURE2DARRAY */
ATTRIBUTE = 316, /* ATTRIBUTE */
VARYING = 317, /* VARYING */
FLOAT16_T = 318, /* FLOAT16_T */
FLOAT32_T = 319, /* FLOAT32_T */
DOUBLE = 320, /* DOUBLE */
FLOAT64_T = 321, /* FLOAT64_T */
INT64_T = 322, /* INT64_T */
UINT64_T = 323, /* UINT64_T */
INT32_T = 324, /* INT32_T */
UINT32_T = 325, /* UINT32_T */
INT16_T = 326, /* INT16_T */
UINT16_T = 327, /* UINT16_T */
INT8_T = 328, /* INT8_T */
UINT8_T = 329, /* UINT8_T */
I64VEC2 = 330, /* I64VEC2 */
I64VEC3 = 331, /* I64VEC3 */
I64VEC4 = 332, /* I64VEC4 */
U64VEC2 = 333, /* U64VEC2 */
U64VEC3 = 334, /* U64VEC3 */
U64VEC4 = 335, /* U64VEC4 */
I32VEC2 = 336, /* I32VEC2 */
I32VEC3 = 337, /* I32VEC3 */
I32VEC4 = 338, /* I32VEC4 */
U32VEC2 = 339, /* U32VEC2 */
U32VEC3 = 340, /* U32VEC3 */
U32VEC4 = 341, /* U32VEC4 */
I16VEC2 = 342, /* I16VEC2 */
I16VEC3 = 343, /* I16VEC3 */
I16VEC4 = 344, /* I16VEC4 */
U16VEC2 = 345, /* U16VEC2 */
U16VEC3 = 346, /* U16VEC3 */
U16VEC4 = 347, /* U16VEC4 */
I8VEC2 = 348, /* I8VEC2 */
I8VEC3 = 349, /* I8VEC3 */
I8VEC4 = 350, /* I8VEC4 */
U8VEC2 = 351, /* U8VEC2 */
U8VEC3 = 352, /* U8VEC3 */
U8VEC4 = 353, /* U8VEC4 */
DVEC2 = 354, /* DVEC2 */
DVEC3 = 355, /* DVEC3 */
DVEC4 = 356, /* DVEC4 */
DMAT2 = 357, /* DMAT2 */
DMAT3 = 358, /* DMAT3 */
DMAT4 = 359, /* DMAT4 */
F16VEC2 = 360, /* F16VEC2 */
F16VEC3 = 361, /* F16VEC3 */
F16VEC4 = 362, /* F16VEC4 */
F16MAT2 = 363, /* F16MAT2 */
F16MAT3 = 364, /* F16MAT3 */
F16MAT4 = 365, /* F16MAT4 */
F32VEC2 = 366, /* F32VEC2 */
F32VEC3 = 367, /* F32VEC3 */
F32VEC4 = 368, /* F32VEC4 */
F32MAT2 = 369, /* F32MAT2 */
F32MAT3 = 370, /* F32MAT3 */
F32MAT4 = 371, /* F32MAT4 */
F64VEC2 = 372, /* F64VEC2 */
F64VEC3 = 373, /* F64VEC3 */
F64VEC4 = 374, /* F64VEC4 */
F64MAT2 = 375, /* F64MAT2 */
F64MAT3 = 376, /* F64MAT3 */
F64MAT4 = 377, /* F64MAT4 */
DMAT2X2 = 378, /* DMAT2X2 */
DMAT2X3 = 379, /* DMAT2X3 */
DMAT2X4 = 380, /* DMAT2X4 */
DMAT3X2 = 381, /* DMAT3X2 */
DMAT3X3 = 382, /* DMAT3X3 */
DMAT3X4 = 383, /* DMAT3X4 */
DMAT4X2 = 384, /* DMAT4X2 */
DMAT4X3 = 385, /* DMAT4X3 */
DMAT4X4 = 386, /* DMAT4X4 */
F16MAT2X2 = 387, /* F16MAT2X2 */
F16MAT2X3 = 388, /* F16MAT2X3 */
F16MAT2X4 = 389, /* F16MAT2X4 */
F16MAT3X2 = 390, /* F16MAT3X2 */
F16MAT3X3 = 391, /* F16MAT3X3 */
F16MAT3X4 = 392, /* F16MAT3X4 */
F16MAT4X2 = 393, /* F16MAT4X2 */
F16MAT4X3 = 394, /* F16MAT4X3 */
F16MAT4X4 = 395, /* F16MAT4X4 */
F32MAT2X2 = 396, /* F32MAT2X2 */
F32MAT2X3 = 397, /* F32MAT2X3 */
F32MAT2X4 = 398, /* F32MAT2X4 */
F32MAT3X2 = 399, /* F32MAT3X2 */
F32MAT3X3 = 400, /* F32MAT3X3 */
F32MAT3X4 = 401, /* F32MAT3X4 */
F32MAT4X2 = 402, /* F32MAT4X2 */
F32MAT4X3 = 403, /* F32MAT4X3 */
F32MAT4X4 = 404, /* F32MAT4X4 */
F64MAT2X2 = 405, /* F64MAT2X2 */
F64MAT2X3 = 406, /* F64MAT2X3 */
F64MAT2X4 = 407, /* F64MAT2X4 */
F64MAT3X2 = 408, /* F64MAT3X2 */
F64MAT3X3 = 409, /* F64MAT3X3 */
F64MAT3X4 = 410, /* F64MAT3X4 */
F64MAT4X2 = 411, /* F64MAT4X2 */
F64MAT4X3 = 412, /* F64MAT4X3 */
F64MAT4X4 = 413, /* F64MAT4X4 */
ATOMIC_UINT = 414, /* ATOMIC_UINT */
ACCSTRUCTNV = 415, /* ACCSTRUCTNV */
ACCSTRUCTEXT = 416, /* ACCSTRUCTEXT */
RAYQUERYEXT = 417, /* RAYQUERYEXT */
FCOOPMATNV = 418, /* FCOOPMATNV */
ICOOPMATNV = 419, /* ICOOPMATNV */
UCOOPMATNV = 420, /* UCOOPMATNV */
SAMPLERCUBEARRAY = 421, /* SAMPLERCUBEARRAY */
SAMPLERCUBEARRAYSHADOW = 422, /* SAMPLERCUBEARRAYSHADOW */
ISAMPLERCUBEARRAY = 423, /* ISAMPLERCUBEARRAY */
USAMPLERCUBEARRAY = 424, /* USAMPLERCUBEARRAY */
SAMPLER1D = 425, /* SAMPLER1D */
SAMPLER1DARRAY = 426, /* SAMPLER1DARRAY */
SAMPLER1DARRAYSHADOW = 427, /* SAMPLER1DARRAYSHADOW */
ISAMPLER1D = 428, /* ISAMPLER1D */
SAMPLER1DSHADOW = 429, /* SAMPLER1DSHADOW */
SAMPLER2DRECT = 430, /* SAMPLER2DRECT */
SAMPLER2DRECTSHADOW = 431, /* SAMPLER2DRECTSHADOW */
ISAMPLER2DRECT = 432, /* ISAMPLER2DRECT */
USAMPLER2DRECT = 433, /* USAMPLER2DRECT */
SAMPLERBUFFER = 434, /* SAMPLERBUFFER */
ISAMPLERBUFFER = 435, /* ISAMPLERBUFFER */
USAMPLERBUFFER = 436, /* USAMPLERBUFFER */
SAMPLER2DMS = 437, /* SAMPLER2DMS */
ISAMPLER2DMS = 438, /* ISAMPLER2DMS */
USAMPLER2DMS = 439, /* USAMPLER2DMS */
SAMPLER2DMSARRAY = 440, /* SAMPLER2DMSARRAY */
ISAMPLER2DMSARRAY = 441, /* ISAMPLER2DMSARRAY */
USAMPLER2DMSARRAY = 442, /* USAMPLER2DMSARRAY */
SAMPLEREXTERNALOES = 443, /* SAMPLEREXTERNALOES */
SAMPLEREXTERNAL2DY2YEXT = 444, /* SAMPLEREXTERNAL2DY2YEXT */
ISAMPLER1DARRAY = 445, /* ISAMPLER1DARRAY */
USAMPLER1D = 446, /* USAMPLER1D */
USAMPLER1DARRAY = 447, /* USAMPLER1DARRAY */
F16SAMPLER1D = 448, /* F16SAMPLER1D */
F16SAMPLER2D = 449, /* F16SAMPLER2D */
F16SAMPLER3D = 450, /* F16SAMPLER3D */
F16SAMPLER2DRECT = 451, /* F16SAMPLER2DRECT */
F16SAMPLERCUBE = 452, /* F16SAMPLERCUBE */
F16SAMPLER1DARRAY = 453, /* F16SAMPLER1DARRAY */
F16SAMPLER2DARRAY = 454, /* F16SAMPLER2DARRAY */
F16SAMPLERCUBEARRAY = 455, /* F16SAMPLERCUBEARRAY */
F16SAMPLERBUFFER = 456, /* F16SAMPLERBUFFER */
F16SAMPLER2DMS = 457, /* F16SAMPLER2DMS */
F16SAMPLER2DMSARRAY = 458, /* F16SAMPLER2DMSARRAY */
F16SAMPLER1DSHADOW = 459, /* F16SAMPLER1DSHADOW */
F16SAMPLER2DSHADOW = 460, /* F16SAMPLER2DSHADOW */
F16SAMPLER1DARRAYSHADOW = 461, /* F16SAMPLER1DARRAYSHADOW */
F16SAMPLER2DARRAYSHADOW = 462, /* F16SAMPLER2DARRAYSHADOW */
F16SAMPLER2DRECTSHADOW = 463, /* F16SAMPLER2DRECTSHADOW */
F16SAMPLERCUBESHADOW = 464, /* F16SAMPLERCUBESHADOW */
F16SAMPLERCUBEARRAYSHADOW = 465, /* F16SAMPLERCUBEARRAYSHADOW */
IMAGE1D = 466, /* IMAGE1D */
IIMAGE1D = 467, /* IIMAGE1D */
UIMAGE1D = 468, /* UIMAGE1D */
IMAGE2D = 469, /* IMAGE2D */
IIMAGE2D = 470, /* IIMAGE2D */
UIMAGE2D = 471, /* UIMAGE2D */
IMAGE3D = 472, /* IMAGE3D */
IIMAGE3D = 473, /* IIMAGE3D */
UIMAGE3D = 474, /* UIMAGE3D */
IMAGE2DRECT = 475, /* IMAGE2DRECT */
IIMAGE2DRECT = 476, /* IIMAGE2DRECT */
UIMAGE2DRECT = 477, /* UIMAGE2DRECT */
IMAGECUBE = 478, /* IMAGECUBE */
IIMAGECUBE = 479, /* IIMAGECUBE */
UIMAGECUBE = 480, /* UIMAGECUBE */
IMAGEBUFFER = 481, /* IMAGEBUFFER */
IIMAGEBUFFER = 482, /* IIMAGEBUFFER */
UIMAGEBUFFER = 483, /* UIMAGEBUFFER */
IMAGE1DARRAY = 484, /* IMAGE1DARRAY */
IIMAGE1DARRAY = 485, /* IIMAGE1DARRAY */
UIMAGE1DARRAY = 486, /* UIMAGE1DARRAY */
IMAGE2DARRAY = 487, /* IMAGE2DARRAY */
IIMAGE2DARRAY = 488, /* IIMAGE2DARRAY */
UIMAGE2DARRAY = 489, /* UIMAGE2DARRAY */
IMAGECUBEARRAY = 490, /* IMAGECUBEARRAY */
IIMAGECUBEARRAY = 491, /* IIMAGECUBEARRAY */
UIMAGECUBEARRAY = 492, /* UIMAGECUBEARRAY */
IMAGE2DMS = 493, /* IMAGE2DMS */
IIMAGE2DMS = 494, /* IIMAGE2DMS */
UIMAGE2DMS = 495, /* UIMAGE2DMS */
IMAGE2DMSARRAY = 496, /* IMAGE2DMSARRAY */
IIMAGE2DMSARRAY = 497, /* IIMAGE2DMSARRAY */
UIMAGE2DMSARRAY = 498, /* UIMAGE2DMSARRAY */
F16IMAGE1D = 499, /* F16IMAGE1D */
F16IMAGE2D = 500, /* F16IMAGE2D */
F16IMAGE3D = 501, /* F16IMAGE3D */
F16IMAGE2DRECT = 502, /* F16IMAGE2DRECT */
F16IMAGECUBE = 503, /* F16IMAGECUBE */
F16IMAGE1DARRAY = 504, /* F16IMAGE1DARRAY */
F16IMAGE2DARRAY = 505, /* F16IMAGE2DARRAY */
F16IMAGECUBEARRAY = 506, /* F16IMAGECUBEARRAY */
F16IMAGEBUFFER = 507, /* F16IMAGEBUFFER */
F16IMAGE2DMS = 508, /* F16IMAGE2DMS */
F16IMAGE2DMSARRAY = 509, /* F16IMAGE2DMSARRAY */
I64IMAGE1D = 510, /* I64IMAGE1D */
U64IMAGE1D = 511, /* U64IMAGE1D */
I64IMAGE2D = 512, /* I64IMAGE2D */
U64IMAGE2D = 513, /* U64IMAGE2D */
I64IMAGE3D = 514, /* I64IMAGE3D */
U64IMAGE3D = 515, /* U64IMAGE3D */
I64IMAGE2DRECT = 516, /* I64IMAGE2DRECT */
U64IMAGE2DRECT = 517, /* U64IMAGE2DRECT */
I64IMAGECUBE = 518, /* I64IMAGECUBE */
U64IMAGECUBE = 519, /* U64IMAGECUBE */
I64IMAGEBUFFER = 520, /* I64IMAGEBUFFER */
U64IMAGEBUFFER = 521, /* U64IMAGEBUFFER */
I64IMAGE1DARRAY = 522, /* I64IMAGE1DARRAY */
U64IMAGE1DARRAY = 523, /* U64IMAGE1DARRAY */
I64IMAGE2DARRAY = 524, /* I64IMAGE2DARRAY */
U64IMAGE2DARRAY = 525, /* U64IMAGE2DARRAY */
I64IMAGECUBEARRAY = 526, /* I64IMAGECUBEARRAY */
U64IMAGECUBEARRAY = 527, /* U64IMAGECUBEARRAY */
I64IMAGE2DMS = 528, /* I64IMAGE2DMS */
U64IMAGE2DMS = 529, /* U64IMAGE2DMS */
I64IMAGE2DMSARRAY = 530, /* I64IMAGE2DMSARRAY */
U64IMAGE2DMSARRAY = 531, /* U64IMAGE2DMSARRAY */
TEXTURECUBEARRAY = 532, /* TEXTURECUBEARRAY */
ITEXTURECUBEARRAY = 533, /* ITEXTURECUBEARRAY */
UTEXTURECUBEARRAY = 534, /* UTEXTURECUBEARRAY */
TEXTURE1D = 535, /* TEXTURE1D */
ITEXTURE1D = 536, /* ITEXTURE1D */
UTEXTURE1D = 537, /* UTEXTURE1D */
TEXTURE1DARRAY = 538, /* TEXTURE1DARRAY */
ITEXTURE1DARRAY = 539, /* ITEXTURE1DARRAY */
UTEXTURE1DARRAY = 540, /* UTEXTURE1DARRAY */
TEXTURE2DRECT = 541, /* TEXTURE2DRECT */
ITEXTURE2DRECT = 542, /* ITEXTURE2DRECT */
UTEXTURE2DRECT = 543, /* UTEXTURE2DRECT */
TEXTUREBUFFER = 544, /* TEXTUREBUFFER */
ITEXTUREBUFFER = 545, /* ITEXTUREBUFFER */
UTEXTUREBUFFER = 546, /* UTEXTUREBUFFER */
TEXTURE2DMS = 547, /* TEXTURE2DMS */
ITEXTURE2DMS = 548, /* ITEXTURE2DMS */
UTEXTURE2DMS = 549, /* UTEXTURE2DMS */
TEXTURE2DMSARRAY = 550, /* TEXTURE2DMSARRAY */
ITEXTURE2DMSARRAY = 551, /* ITEXTURE2DMSARRAY */
UTEXTURE2DMSARRAY = 552, /* UTEXTURE2DMSARRAY */
F16TEXTURE1D = 553, /* F16TEXTURE1D */
F16TEXTURE2D = 554, /* F16TEXTURE2D */
F16TEXTURE3D = 555, /* F16TEXTURE3D */
F16TEXTURE2DRECT = 556, /* F16TEXTURE2DRECT */
F16TEXTURECUBE = 557, /* F16TEXTURECUBE */
F16TEXTURE1DARRAY = 558, /* F16TEXTURE1DARRAY */
F16TEXTURE2DARRAY = 559, /* F16TEXTURE2DARRAY */
F16TEXTURECUBEARRAY = 560, /* F16TEXTURECUBEARRAY */
F16TEXTUREBUFFER = 561, /* F16TEXTUREBUFFER */
F16TEXTURE2DMS = 562, /* F16TEXTURE2DMS */
F16TEXTURE2DMSARRAY = 563, /* F16TEXTURE2DMSARRAY */
SUBPASSINPUT = 564, /* SUBPASSINPUT */
SUBPASSINPUTMS = 565, /* SUBPASSINPUTMS */
ISUBPASSINPUT = 566, /* ISUBPASSINPUT */
ISUBPASSINPUTMS = 567, /* ISUBPASSINPUTMS */
USUBPASSINPUT = 568, /* USUBPASSINPUT */
USUBPASSINPUTMS = 569, /* USUBPASSINPUTMS */
F16SUBPASSINPUT = 570, /* F16SUBPASSINPUT */
F16SUBPASSINPUTMS = 571, /* F16SUBPASSINPUTMS */
SPIRV_INSTRUCTION = 572, /* SPIRV_INSTRUCTION */
SPIRV_EXECUTION_MODE = 573, /* SPIRV_EXECUTION_MODE */
SPIRV_EXECUTION_MODE_ID = 574, /* SPIRV_EXECUTION_MODE_ID */
SPIRV_DECORATE = 575, /* SPIRV_DECORATE */
SPIRV_DECORATE_ID = 576, /* SPIRV_DECORATE_ID */
SPIRV_DECORATE_STRING = 577, /* SPIRV_DECORATE_STRING */
SPIRV_TYPE = 578, /* SPIRV_TYPE */
SPIRV_STORAGE_CLASS = 579, /* SPIRV_STORAGE_CLASS */
SPIRV_BY_REFERENCE = 580, /* SPIRV_BY_REFERENCE */
SPIRV_LITERAL = 581, /* SPIRV_LITERAL */
LEFT_OP = 582, /* LEFT_OP */
RIGHT_OP = 583, /* RIGHT_OP */
INC_OP = 584, /* INC_OP */
DEC_OP = 585, /* DEC_OP */
LE_OP = 586, /* LE_OP */
GE_OP = 587, /* GE_OP */
EQ_OP = 588, /* EQ_OP */
NE_OP = 589, /* NE_OP */
AND_OP = 590, /* AND_OP */
OR_OP = 591, /* OR_OP */
XOR_OP = 592, /* XOR_OP */
MUL_ASSIGN = 593, /* MUL_ASSIGN */
DIV_ASSIGN = 594, /* DIV_ASSIGN */
ADD_ASSIGN = 595, /* ADD_ASSIGN */
MOD_ASSIGN = 596, /* MOD_ASSIGN */
LEFT_ASSIGN = 597, /* LEFT_ASSIGN */
RIGHT_ASSIGN = 598, /* RIGHT_ASSIGN */
AND_ASSIGN = 599, /* AND_ASSIGN */
XOR_ASSIGN = 600, /* XOR_ASSIGN */
OR_ASSIGN = 601, /* OR_ASSIGN */
SUB_ASSIGN = 602, /* SUB_ASSIGN */
STRING_LITERAL = 603, /* STRING_LITERAL */
LEFT_PAREN = 604, /* LEFT_PAREN */
RIGHT_PAREN = 605, /* RIGHT_PAREN */
LEFT_BRACKET = 606, /* LEFT_BRACKET */
RIGHT_BRACKET = 607, /* RIGHT_BRACKET */
LEFT_BRACE = 608, /* LEFT_BRACE */
RIGHT_BRACE = 609, /* RIGHT_BRACE */
DOT = 610, /* DOT */
COMMA = 611, /* COMMA */
COLON = 612, /* COLON */
EQUAL = 613, /* EQUAL */
SEMICOLON = 614, /* SEMICOLON */
BANG = 615, /* BANG */
DASH = 616, /* DASH */
TILDE = 617, /* TILDE */
PLUS = 618, /* PLUS */
STAR = 619, /* STAR */
SLASH = 620, /* SLASH */
PERCENT = 621, /* PERCENT */
LEFT_ANGLE = 622, /* LEFT_ANGLE */
RIGHT_ANGLE = 623, /* RIGHT_ANGLE */
VERTICAL_BAR = 624, /* VERTICAL_BAR */
CARET = 625, /* CARET */
AMPERSAND = 626, /* AMPERSAND */
QUESTION = 627, /* QUESTION */
INVARIANT = 628, /* INVARIANT */
HIGH_PRECISION = 629, /* HIGH_PRECISION */
MEDIUM_PRECISION = 630, /* MEDIUM_PRECISION */
LOW_PRECISION = 631, /* LOW_PRECISION */
PRECISION = 632, /* PRECISION */
PACKED = 633, /* PACKED */
RESOURCE = 634, /* RESOURCE */
SUPERP = 635, /* SUPERP */
FLOATCONSTANT = 636, /* FLOATCONSTANT */
INTCONSTANT = 637, /* INTCONSTANT */
UINTCONSTANT = 638, /* UINTCONSTANT */
BOOLCONSTANT = 639, /* BOOLCONSTANT */
IDENTIFIER = 640, /* IDENTIFIER */
TYPE_NAME = 641, /* TYPE_NAME */
CENTROID = 642, /* CENTROID */
IN = 643, /* IN */
OUT = 644, /* OUT */
INOUT = 645, /* INOUT */
STRUCT = 646, /* STRUCT */
VOID = 647, /* VOID */
WHILE = 648, /* WHILE */
BREAK = 649, /* BREAK */
CONTINUE = 650, /* CONTINUE */
DO = 651, /* DO */
ELSE = 652, /* ELSE */
FOR = 653, /* FOR */
IF = 654, /* IF */
DISCARD = 655, /* DISCARD */
RETURN = 656, /* RETURN */
SWITCH = 657, /* SWITCH */
CASE = 658, /* CASE */
DEFAULT = 659, /* DEFAULT */
TERMINATE_INVOCATION = 660, /* TERMINATE_INVOCATION */
TERMINATE_RAY = 661, /* TERMINATE_RAY */
IGNORE_INTERSECTION = 662, /* IGNORE_INTERSECTION */
UNIFORM = 663, /* UNIFORM */
SHARED = 664, /* SHARED */
BUFFER = 665, /* BUFFER */
FLAT = 666, /* FLAT */
SMOOTH = 667, /* SMOOTH */
LAYOUT = 668, /* LAYOUT */
DOUBLECONSTANT = 669, /* DOUBLECONSTANT */
INT16CONSTANT = 670, /* INT16CONSTANT */
UINT16CONSTANT = 671, /* UINT16CONSTANT */
FLOAT16CONSTANT = 672, /* FLOAT16CONSTANT */
INT32CONSTANT = 673, /* INT32CONSTANT */
UINT32CONSTANT = 674, /* UINT32CONSTANT */
INT64CONSTANT = 675, /* INT64CONSTANT */
UINT64CONSTANT = 676, /* UINT64CONSTANT */
SUBROUTINE = 677, /* SUBROUTINE */
DEMOTE = 678, /* DEMOTE */
PAYLOADNV = 679, /* PAYLOADNV */
PAYLOADINNV = 680, /* PAYLOADINNV */
HITATTRNV = 681, /* HITATTRNV */
CALLDATANV = 682, /* CALLDATANV */
CALLDATAINNV = 683, /* CALLDATAINNV */
PAYLOADEXT = 684, /* PAYLOADEXT */
PAYLOADINEXT = 685, /* PAYLOADINEXT */
HITATTREXT = 686, /* HITATTREXT */
CALLDATAEXT = 687, /* CALLDATAEXT */
CALLDATAINEXT = 688, /* CALLDATAINEXT */
PATCH = 689, /* PATCH */
SAMPLE = 690, /* SAMPLE */
NONUNIFORM = 691, /* NONUNIFORM */
COHERENT = 692, /* COHERENT */
VOLATILE = 693, /* VOLATILE */
RESTRICT = 694, /* RESTRICT */
READONLY = 695, /* READONLY */
WRITEONLY = 696, /* WRITEONLY */
DEVICECOHERENT = 697, /* DEVICECOHERENT */
QUEUEFAMILYCOHERENT = 698, /* QUEUEFAMILYCOHERENT */
WORKGROUPCOHERENT = 699, /* WORKGROUPCOHERENT */
SUBGROUPCOHERENT = 700, /* SUBGROUPCOHERENT */
NONPRIVATE = 701, /* NONPRIVATE */
SHADERCALLCOHERENT = 702, /* SHADERCALLCOHERENT */
NOPERSPECTIVE = 703, /* NOPERSPECTIVE */
EXPLICITINTERPAMD = 704, /* EXPLICITINTERPAMD */
PERVERTEXEXT = 705, /* PERVERTEXEXT */
PERVERTEXNV = 706, /* PERVERTEXNV */
PERPRIMITIVENV = 707, /* PERPRIMITIVENV */
PERVIEWNV = 708, /* PERVIEWNV */
PERTASKNV = 709, /* PERTASKNV */
PRECISE = 710 /* PRECISE */
};
typedef enum yytokentype yytoken_kind_t;
#endif
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
union YYSTYPE
{
#line 96 "MachineIndependent/glslang.y" /* yacc.c:1909 */
#line 97 "MachineIndependent/glslang.y"
struct {
glslang::TSourceLoc loc;
@ -484,6 +538,9 @@ union YYSTYPE
glslang::TIntermNodePair nodePair;
glslang::TIntermTyped* intermTypedNode;
glslang::TAttributes* attributes;
glslang::TSpirvRequirement* spirvReq;
glslang::TSpirvInstruction* spirvInst;
glslang::TSpirvTypeParameters* spirvTypeParams;
};
union {
glslang::TPublicType type;
@ -497,9 +554,9 @@ union YYSTYPE
glslang::TArraySizes* typeParameters;
} interm;
#line 501 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909 */
};
#line 558 "MachineIndependent/glslang_tab.cpp.h"
};
typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1

View file

@ -2,6 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2016 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@ -35,7 +36,7 @@
// POSSIBILITY OF SUCH DAMAGE.
//
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
#include "localintermediate.h"
#include "../Include/InfoSink.h"
@ -47,37 +48,6 @@
#endif
#include <cstdint>
namespace {
bool IsInfinity(double x) {
#ifdef _MSC_VER
switch (_fpclass(x)) {
case _FPCLASS_NINF:
case _FPCLASS_PINF:
return true;
default:
return false;
}
#else
return std::isinf(x);
#endif
}
bool IsNan(double x) {
#ifdef _MSC_VER
switch (_fpclass(x)) {
case _FPCLASS_SNAN:
case _FPCLASS_QNAN:
return true;
default:
return false;
}
#else
return std::isnan(x);
#endif
}
}
namespace glslang {
@ -437,6 +407,9 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
case EOpConvUint64ToPtr: out.debug << "Convert uint64_t to pointer"; break;
case EOpConvPtrToUint64: out.debug << "Convert pointer to uint64_t"; break;
case EOpConvUint64ToAccStruct: out.debug << "Convert uint64_t to acceleration structure"; break;
case EOpConvUvec2ToAccStruct: out.debug << "Convert uvec2 to acceleration strucuture "; break;
case EOpRadians: out.debug << "radians"; break;
case EOpDegrees: out.debug << "degrees"; break;
case EOpSin: out.debug << "sine"; break;
@ -692,6 +665,10 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
case EOpConstructReference: out.debug << "Construct reference type"; break;
#ifndef GLSLANG_WEB
case EOpSpirvInst: out.debug << "spirv_instruction"; break;
#endif
default: out.debug.message(EPrefixError, "Bad unary op");
}
@ -828,6 +805,7 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpConstructTextureSampler: out.debug << "Construct combined texture-sampler"; break;
case EOpConstructReference: out.debug << "Construct reference"; break;
case EOpConstructCooperativeMatrix: out.debug << "Construct cooperative matrix"; break;
case EOpConstructAccStruct: out.debug << "Construct acceleration structure"; break;
case EOpLessThan: out.debug << "Compare Less Than"; break;
case EOpGreaterThan: out.debug << "Compare Greater Than"; break;
@ -881,6 +859,7 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpTime: out.debug << "time"; break;
case EOpAtomicAdd: out.debug << "AtomicAdd"; break;
case EOpAtomicSubtract: out.debug << "AtomicSubtract"; break;
case EOpAtomicMin: out.debug << "AtomicMin"; break;
case EOpAtomicMax: out.debug << "AtomicMax"; break;
case EOpAtomicAnd: out.debug << "AtomicAnd"; break;
@ -1079,17 +1058,51 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
case EOpTraceNV: out.debug << "traceNV"; break;
case EOpReportIntersectionNV: out.debug << "reportIntersectionNV"; break;
case EOpTraceRayMotionNV: out.debug << "traceRayMotionNV"; break;
case EOpTraceKHR: out.debug << "traceRayKHR"; break;
case EOpReportIntersection: out.debug << "reportIntersectionNV"; break;
case EOpIgnoreIntersectionNV: out.debug << "ignoreIntersectionNV"; break;
case EOpIgnoreIntersectionKHR: out.debug << "ignoreIntersectionKHR"; break;
case EOpTerminateRayNV: out.debug << "terminateRayNV"; break;
case EOpTerminateRayKHR: out.debug << "terminateRayKHR"; break;
case EOpExecuteCallableNV: out.debug << "executeCallableNV"; break;
case EOpExecuteCallableKHR: out.debug << "executeCallableKHR"; break;
case EOpWritePackedPrimitiveIndices4x8NV: out.debug << "writePackedPrimitiveIndices4x8NV"; break;
case EOpRayQueryInitialize: out.debug << "rayQueryInitializeEXT"; break;
case EOpRayQueryTerminate: out.debug << "rayQueryTerminateEXT"; break;
case EOpRayQueryGenerateIntersection: out.debug << "rayQueryGenerateIntersectionEXT"; break;
case EOpRayQueryConfirmIntersection: out.debug << "rayQueryConfirmIntersectionEXT"; break;
case EOpRayQueryProceed: out.debug << "rayQueryProceedEXT"; break;
case EOpRayQueryGetIntersectionType: out.debug << "rayQueryGetIntersectionTypeEXT"; break;
case EOpRayQueryGetRayTMin: out.debug << "rayQueryGetRayTMinEXT"; break;
case EOpRayQueryGetRayFlags: out.debug << "rayQueryGetRayFlagsEXT"; break;
case EOpRayQueryGetIntersectionT: out.debug << "rayQueryGetIntersectionTEXT"; break;
case EOpRayQueryGetIntersectionInstanceCustomIndex: out.debug << "rayQueryGetIntersectionInstanceCustomIndexEXT"; break;
case EOpRayQueryGetIntersectionInstanceId: out.debug << "rayQueryGetIntersectionInstanceIdEXT"; break;
case EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: out.debug << "rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT"; break;
case EOpRayQueryGetIntersectionGeometryIndex: out.debug << "rayQueryGetIntersectionGeometryIndexEXT"; break;
case EOpRayQueryGetIntersectionPrimitiveIndex: out.debug << "rayQueryGetIntersectionPrimitiveIndexEXT"; break;
case EOpRayQueryGetIntersectionBarycentrics: out.debug << "rayQueryGetIntersectionBarycentricsEXT"; break;
case EOpRayQueryGetIntersectionFrontFace: out.debug << "rayQueryGetIntersectionFrontFaceEXT"; break;
case EOpRayQueryGetIntersectionCandidateAABBOpaque: out.debug << "rayQueryGetIntersectionCandidateAABBOpaqueEXT"; break;
case EOpRayQueryGetIntersectionObjectRayDirection: out.debug << "rayQueryGetIntersectionObjectRayDirectionEXT"; break;
case EOpRayQueryGetIntersectionObjectRayOrigin: out.debug << "rayQueryGetIntersectionObjectRayOriginEXT"; break;
case EOpRayQueryGetWorldRayDirection: out.debug << "rayQueryGetWorldRayDirectionEXT"; break;
case EOpRayQueryGetWorldRayOrigin: out.debug << "rayQueryGetWorldRayOriginEXT"; break;
case EOpRayQueryGetIntersectionObjectToWorld: out.debug << "rayQueryGetIntersectionObjectToWorldEXT"; break;
case EOpRayQueryGetIntersectionWorldToObject: out.debug << "rayQueryGetIntersectionWorldToObjectEXT"; break;
case EOpCooperativeMatrixLoad: out.debug << "Load cooperative matrix"; break;
case EOpCooperativeMatrixStore: out.debug << "Store cooperative matrix"; break;
case EOpCooperativeMatrixMulAdd: out.debug << "MulAdd cooperative matrices"; break;
case EOpIsHelperInvocation: out.debug << "IsHelperInvocation"; break;
case EOpDebugPrintf: out.debug << "Debug printf"; break;
#ifndef GLSLANG_WEB
case EOpSpirvInst: out.debug << "spirv_instruction"; break;
#endif
default: out.debug.message(EPrefixError, "Bad aggregation op");
}
@ -1295,6 +1308,9 @@ static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const
out.debug << buf << "\n";
}
break;
case EbtString:
out.debug << "\"" << constUnion[i].getSConst()->c_str() << "\"\n";
break;
default:
out.info.message(EPrefixInternalError, "Unknown constant", node->getLoc());
break;
@ -1380,14 +1396,17 @@ bool TOutputTraverser::visitBranch(TVisit /* visit*/, TIntermBranch* node)
OutputTreeText(out, node, depth);
switch (node->getFlowOp()) {
case EOpKill: out.debug << "Branch: Kill"; break;
case EOpBreak: out.debug << "Branch: Break"; break;
case EOpContinue: out.debug << "Branch: Continue"; break;
case EOpReturn: out.debug << "Branch: Return"; break;
case EOpCase: out.debug << "case: "; break;
case EOpDemote: out.debug << "Demote"; break;
case EOpDefault: out.debug << "default: "; break;
default: out.debug << "Branch: Unknown Branch"; break;
case EOpKill: out.debug << "Branch: Kill"; break;
case EOpTerminateInvocation: out.debug << "Branch: TerminateInvocation"; break;
case EOpIgnoreIntersectionKHR: out.debug << "Branch: IgnoreIntersectionKHR"; break;
case EOpTerminateRayKHR: out.debug << "Branch: TerminateRayKHR"; break;
case EOpBreak: out.debug << "Branch: Break"; break;
case EOpContinue: out.debug << "Branch: Continue"; break;
case EOpReturn: out.debug << "Branch: Return"; break;
case EOpCase: out.debug << "case: "; break;
case EOpDemote: out.debug << "Demote"; break;
case EOpDefault: out.debug << "default: "; break;
default: out.debug << "Branch: Unknown Branch"; break;
}
if (node->getExpression()) {
@ -1446,6 +1465,9 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
if (xfbMode)
infoSink.debug << "in xfb mode\n";
if (getSubgroupUniformControlFlow())
infoSink.debug << "subgroup_uniform_control_flow\n";
switch (language) {
case EShLangVertex:
break;
@ -1536,4 +1558,4 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
} // end namespace glslang
#endif // not GLSLANG_WEB
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE

File diff suppressed because it is too large Load diff

View file

@ -33,7 +33,7 @@
// POSSIBILITY OF SUCH DAMAGE.
//
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
#ifndef _IOMAPPER_INCLUDED
#define _IOMAPPER_INCLUDED
@ -52,7 +52,7 @@ namespace glslang {
class TIntermediate;
struct TVarEntryInfo {
int id;
long long id;
TIntermSymbol* symbol;
bool live;
int newBinding;
@ -61,6 +61,15 @@ struct TVarEntryInfo {
int newComponent;
int newIndex;
EShLanguage stage;
void clearNewAssignments() {
newBinding = -1;
newSet = -1;
newLocation = -1;
newComponent = -1;
newIndex = -1;
}
struct TOrderById {
inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { return l.id < r.id; }
};
@ -87,6 +96,35 @@ struct TVarEntryInfo {
return lPoints > rPoints;
}
};
struct TOrderByPriorityAndLive {
// ordering:
// 1) do live variables first
// 2) has both binding and set
// 3) has binding but no set
// 4) has no binding but set
// 5) has no binding and no set
inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) {
const TQualifier& lq = l.symbol->getQualifier();
const TQualifier& rq = r.symbol->getQualifier();
// simple rules:
// has binding gives 2 points
// has set gives 1 point
// who has the most points is more important.
int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0);
int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0);
if (l.live != r.live)
return l.live > r.live;
if (lPoints != rPoints)
return lPoints > rPoints;
return l.id < r.id;
}
};
};
// Base class for shared TIoMapResolver services, used by several derivations.
@ -107,8 +145,8 @@ public:
void endCollect(EShLanguage) override {}
void reserverResourceSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
void reserverStorageSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
int getBaseBinding(TResourceType res, unsigned int set) const;
const std::vector<std::string>& getResourceSetBinding() const;
int getBaseBinding(EShLanguage stage, TResourceType res, unsigned int set) const;
const std::vector<std::string>& getResourceSetBinding(EShLanguage stage) const;
virtual TResourceType getResourceType(const glslang::TType& type) = 0;
bool doAutoBindingMapping() const;
bool doAutoLocationMapping() const;
@ -122,22 +160,27 @@ public:
int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override;
int resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
int resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
void addStage(EShLanguage stage) override {
if (stage < EShLangCount)
void addStage(EShLanguage stage, TIntermediate& stageIntermediate) override {
if (stage < EShLangCount) {
stageMask[stage] = true;
stageIntermediates[stage] = &stageIntermediate;
}
}
uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage);
TSlotSetMap slots;
bool hasError = false;
protected:
TDefaultIoResolverBase(TDefaultIoResolverBase&);
TDefaultIoResolverBase& operator=(TDefaultIoResolverBase&);
const TIntermediate& intermediate;
const TIntermediate& referenceIntermediate;
int nextUniformLocation;
int nextInputLocation;
int nextOutputLocation;
bool stageMask[EShLangCount + 1];
const TIntermediate* stageIntermediates[EShLangCount];
// Return descriptor set specific base if there is one, and the generic base otherwise.
int selectBaseBinding(int base, int descriptorSetBase) const {
return descriptorSetBase != -1 ? descriptorSetBase : base;
@ -185,7 +228,7 @@ protected:
}
};
// Defaulf I/O resolver for OpenGL
// Default I/O resolver for OpenGL
struct TDefaultGlslIoResolver : public TDefaultIoResolverBase {
public:
typedef std::map<TString, int> TVarSlotMap; // <resourceName, location/binding>
@ -237,12 +280,13 @@ typedef std::map<TString, TVarEntryInfo> TVarLiveMap;
// In the future, if the vc++ compiler can handle such a situation,
// this part of the code will be removed.
struct TVarLivePair : std::pair<const TString, TVarEntryInfo> {
TVarLivePair(std::pair<const TString, TVarEntryInfo>& _Right) : pair(_Right.first, _Right.second) {}
TVarLivePair(const std::pair<const TString, TVarEntryInfo>& _Right) : pair(_Right.first, _Right.second) {}
TVarLivePair& operator=(const TVarLivePair& _Right) {
const_cast<TString&>(first) = _Right.first;
second = _Right.second;
return (*this);
}
TVarLivePair(const TVarLivePair& src) : pair(src) { }
};
typedef std::vector<TVarLivePair> TVarLiveVector;
@ -256,7 +300,7 @@ public:
bool virtual doMap(TIoMapResolver*, TInfoSink&) { return true; }
};
// I/O mapper for OpenGL
// I/O mapper for GLSL
class TGlslIoMapper : public TIoMapper {
public:
TGlslIoMapper() {
@ -264,6 +308,10 @@ public:
memset(outVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
memset(intermediates, 0, sizeof(TIntermediate*) * (EShLangCount + 1));
profile = ENoProfile;
version = 0;
autoPushConstantMaxSize = 128;
autoPushConstantBlockPacking = ElpStd430;
}
virtual ~TGlslIoMapper() {
for (size_t stage = 0; stage < EShLangCount; stage++) {
@ -283,6 +331,13 @@ public:
intermediates[stage] = nullptr;
}
}
// If set, the uniform block with the given name will be changed to be backed by
// push_constant if it's size is <= maxSize
void setAutoPushConstantBlock(const char* name, unsigned int maxSize, TLayoutPacking packing) {
autoPushConstantBlockName = name;
autoPushConstantMaxSize = maxSize;
autoPushConstantBlockPacking = packing;
}
// grow the reflection stage by stage
bool addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*) override;
bool doMap(TIoMapResolver*, TInfoSink&) override;
@ -290,10 +345,17 @@ public:
*uniformVarMap[EShLangCount];
TIntermediate* intermediates[EShLangCount];
bool hadError = false;
EProfile profile;
int version;
private:
TString autoPushConstantBlockName;
unsigned int autoPushConstantMaxSize;
TLayoutPacking autoPushConstantBlockPacking;
};
} // end namespace glslang
#endif // _IOMAPPER_INCLUDED
#endif // GLSLANG_WEB
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE

View file

@ -63,14 +63,14 @@ namespace glslang {
class TInductiveTraverser : public TIntermTraverser {
public:
TInductiveTraverser(int id, TSymbolTable& st)
TInductiveTraverser(long long id, TSymbolTable& st)
: loopId(id), symbolTable(st), bad(false) { }
virtual bool visitBinary(TVisit, TIntermBinary* node);
virtual bool visitUnary(TVisit, TIntermUnary* node);
virtual bool visitAggregate(TVisit, TIntermAggregate* node);
int loopId; // unique ID of the symbol that's the loop inductive variable
long long loopId; // unique ID of the symbol that's the loop inductive variable
TSymbolTable& symbolTable;
bool bad;
TSourceLoc badLoc;
@ -129,7 +129,7 @@ bool TInductiveTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* n
//
// External function to call for loop check.
//
void TParseContext::inductiveLoopBodyCheck(TIntermNode* body, int loopId, TSymbolTable& symbolTable)
void TParseContext::inductiveLoopBodyCheck(TIntermNode* body, long long loopId, TSymbolTable& symbolTable)
{
TInductiveTraverser it(loopId, symbolTable);

File diff suppressed because it is too large Load diff

View file

@ -162,7 +162,10 @@ struct TXfbBuffer {
#endif
// Track a set of strings describing how the module was processed.
// Using the form:
// This includes command line options, transforms, etc., ideally inclusive enough
// to reproduce the steps used to transform the input source to the output.
// E.g., see SPIR-V OpModuleProcessed.
// Each "process" or "transform" uses is expressed in the form:
// process arg0 arg1 arg2 ...
// process arg0 arg1 arg2 ...
// where everything is textual, and there can be zero or more arguments
@ -222,6 +225,57 @@ enum ComputeDerivativeMode {
LayoutDerivativeGroupLinear, // derivative_group_linearNV
};
class TIdMaps {
public:
TMap<TString, long long>& operator[](long long i) { return maps[i]; }
const TMap<TString, long long>& operator[](long long i) const { return maps[i]; }
private:
TMap<TString, long long> maps[EsiCount];
};
class TNumericFeatures {
public:
TNumericFeatures() : features(0) { }
TNumericFeatures(const TNumericFeatures&) = delete;
TNumericFeatures& operator=(const TNumericFeatures&) = delete;
typedef enum : unsigned int {
shader_explicit_arithmetic_types = 1 << 0,
shader_explicit_arithmetic_types_int8 = 1 << 1,
shader_explicit_arithmetic_types_int16 = 1 << 2,
shader_explicit_arithmetic_types_int32 = 1 << 3,
shader_explicit_arithmetic_types_int64 = 1 << 4,
shader_explicit_arithmetic_types_float16 = 1 << 5,
shader_explicit_arithmetic_types_float32 = 1 << 6,
shader_explicit_arithmetic_types_float64 = 1 << 7,
shader_implicit_conversions = 1 << 8,
gpu_shader_fp64 = 1 << 9,
gpu_shader_int16 = 1 << 10,
gpu_shader_half_float = 1 << 11,
} feature;
void insert(feature f) { features |= f; }
void erase(feature f) { features &= ~f; }
bool contains(feature f) const { return (features & f) != 0; }
private:
unsigned int features;
};
// MustBeAssigned wraps a T, asserting that it has been assigned with
// operator =() before attempting to read with operator T() or operator ->().
// Used to catch cases where fields are read before they have been assigned.
template<typename T>
class MustBeAssigned
{
public:
MustBeAssigned() = default;
MustBeAssigned(const T& v) : value(v) {}
operator const T&() const { assert(isSet); return value; }
const T* operator ->() const { assert(isSet); return &value; }
MustBeAssigned& operator = (const T& v) { value = v; isSet = true; return *this; }
private:
T value;
bool isSet = false;
};
//
// Set of helper functions to help parse and build the tree.
//
@ -229,12 +283,25 @@ class TIntermediate {
public:
explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) :
language(l),
profile(p), version(v), treeRoot(0),
#ifndef GLSLANG_ANGLE
profile(p), version(v),
#endif
treeRoot(0),
resources(TBuiltInResource{}),
numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
invertY(false),
dxPositionW(false),
enhancedMsgs(false),
useStorageBuffer(false),
invariantAll(false),
nanMinMaxClamp(false),
depthReplacing(false)
depthReplacing(false),
uniqueId(0),
globalUniformBlockName(""),
atomicCounterBlockName(""),
globalUniformBlockSet(TQualifier::layoutSetEnd),
globalUniformBlockBinding(TQualifier::layoutBindingEnd),
atomicCounterBlockSet(TQualifier::layoutSetEnd)
#ifndef GLSLANG_WEB
,
implicitThisName("@this"), implicitCounterName("@count"),
@ -242,17 +309,18 @@ public:
useVulkanMemoryModel(false),
invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet),
inputPrimitive(ElgNone), outputPrimitive(ElgNone),
pixelCenterInteger(false), originUpperLeft(false),
pixelCenterInteger(false), originUpperLeft(false),texCoordBuiltinRedeclared(false),
vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false),
postDepthCoverage(false), depthLayout(EldNone),
hlslFunctionality1(false),
blendEquations(0), xfbMode(false), multiStream(false),
layoutOverrideCoverage(false),
geoPassthroughEXT(false),
numShaderRecordNVBlocks(0),
numShaderRecordBlocks(0),
computeDerivativeMode(LayoutDerivativeNone),
primitives(TQualifier::layoutNotSet),
numTaskNVBlocks(0),
layoutPrimitiveCulling(false),
autoMapBindings(false),
autoMapLocations(false),
flattenUniformArrays(false),
@ -263,7 +331,10 @@ public:
textureSamplerTransformMode(EShTexSampTransKeep),
needToLegalize(false),
binaryDoubleOutput(false),
subgroupUniformControlFlow(false),
usePhysicalStorageBuffer(false),
spirvRequirement(nullptr),
spirvExecutionMode(nullptr),
uniformLocationBase(0)
#endif
{
@ -282,9 +353,20 @@ public:
#endif
}
void setVersion(int v) { version = v; }
void setVersion(int v)
{
#ifndef GLSLANG_ANGLE
version = v;
#endif
}
void setProfile(EProfile p)
{
#ifndef GLSLANG_ANGLE
profile = p;
#endif
}
int getVersion() const { return version; }
void setProfile(EProfile p) { profile = p; }
EProfile getProfile() const { return profile; }
void setSpv(const SpvVersion& s)
{
@ -317,6 +399,9 @@ public:
case EShTargetSpv_1_5:
processes.addProcess("target-env spirv1.5");
break;
case EShTargetSpv_1_6:
processes.addProcess("target-env spirv1.6");
break;
default:
processes.addProcess("target-env spirvUnknown");
break;
@ -332,6 +417,12 @@ public:
case EShTargetVulkan_1_1:
processes.addProcess("target-env vulkan1.1");
break;
case EShTargetVulkan_1_2:
processes.addProcess("target-env vulkan1.2");
break;
case EShTargetVulkan_1_3:
processes.addProcess("target-env vulkan1.3");
break;
default:
processes.addProcess("target-env vulkanUnknown");
break;
@ -343,6 +434,9 @@ public:
EShLanguage getStage() const { return language; }
void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); }
const std::set<std::string>& getRequestedExtensions() const { return requestedExtensions; }
bool isRayTracingStage() const {
return language >= EShLangRayGen && language <= EShLangCallableNV;
}
void setTreeRoot(TIntermNode* r) { treeRoot = r; }
TIntermNode* getTreeRoot() const { return treeRoot; }
@ -351,6 +445,7 @@ public:
int getNumErrors() const { return numErrors; }
void addPushConstantCount() { ++numPushConstants; }
void setLimits(const TBuiltInResource& r) { resources = r; }
const TBuiltInResource& getLimits() const { return resources; }
bool postProcess(TIntermNode*, EShLanguage);
void removeTree();
@ -373,11 +468,25 @@ public:
}
bool getInvertY() const { return invertY; }
void setDxPositionW(bool dxPosW)
{
dxPositionW = dxPosW;
if (dxPositionW)
processes.addProcess("dx-position-w");
}
bool getDxPositionW() const { return dxPositionW; }
void setEnhancedMsgs()
{
enhancedMsgs = true;
}
bool getEnhancedMsgs() const { return enhancedMsgs && source == EShSourceGlsl; }
#ifdef ENABLE_HLSL
void setSource(EShSource s) { source = s; }
EShSource getSource() const { return source; }
#else
void setSource(EShSource s) { assert(s == EShSourceGlsl); }
void setSource(EShSource s) { assert(s == EShSourceGlsl); (void)s; }
EShSource getSource() const { return EShSourceGlsl; }
#endif
@ -388,15 +497,15 @@ public:
TIntermSymbol* addSymbol(const TType&, const TSourceLoc&);
TIntermSymbol* addSymbol(const TIntermSymbol&);
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
std::tuple<TIntermTyped*, TIntermTyped*> addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1);
std::tuple<TIntermTyped*, TIntermTyped*> addPairConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1);
TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*);
TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const;
void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode);
TIntermTyped* addShapeConversion(const TType&, TIntermTyped*);
TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, TSourceLoc);
TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&);
TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, const TSourceLoc&);
TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType);
bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const;
bool isIntegralPromotion(TBasicType from, TBasicType to) const;
@ -410,7 +519,7 @@ public:
TIntermAggregate* makeAggregate(TIntermNode* node);
TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&);
TIntermAggregate* makeAggregate(const TSourceLoc&);
TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc);
TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, const TSourceLoc&);
bool areAllChildConst(TIntermAggregate* aggrNode);
TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&);
TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&);
@ -439,10 +548,11 @@ public:
// Low level functions to add nodes (no conversions or other higher level transformations)
// If a type is provided, the node's type will be set to it.
TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc) const;
TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, const TType&) const;
TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc) const;
TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc, const TType&) const;
TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&) const;
TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&,
const TType&) const;
TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&) const;
TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&, const TType&) const;
// Constant folding (in Constant.cpp)
TIntermTyped* fold(TIntermAggregate* aggrNode);
@ -451,18 +561,30 @@ public:
TIntermTyped* foldSwizzle(TIntermTyped* node, TSwizzleSelectors<TVectorSelector>& fields, const TSourceLoc&);
// Tree ops
static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay);
static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay , bool BufferReferenceOk = false);
// Linkage related
void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&);
void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&);
TIntermAggregate* findLinkerObjects() const;
void setUseStorageBuffer()
{
useStorageBuffer = true;
processes.addProcess("use-storage-buffer");
}
void setGlobalUniformBlockName(const char* name) { globalUniformBlockName = std::string(name); }
const char* getGlobalUniformBlockName() const { return globalUniformBlockName.c_str(); }
void setGlobalUniformSet(unsigned int set) { globalUniformBlockSet = set; }
unsigned int getGlobalUniformSet() const { return globalUniformBlockSet; }
void setGlobalUniformBinding(unsigned int binding) { globalUniformBlockBinding = binding; }
unsigned int getGlobalUniformBinding() const { return globalUniformBlockBinding; }
void setAtomicCounterBlockName(const char* name) { atomicCounterBlockName = std::string(name); }
const char* getAtomicCounterBlockName() const { return atomicCounterBlockName.c_str(); }
void setAtomicCounterBlockSet(unsigned int set) { atomicCounterBlockSet = set; }
unsigned int getAtomicCounterBlockSet() const { return atomicCounterBlockSet; }
void setUseStorageBuffer() { useStorageBuffer = true; }
bool usingStorageBuffer() const { return useStorageBuffer; }
void setInvariantAll() { invariantAll = true; }
bool isInvariantAll() const { return invariantAll; }
void setDepthReplacing() { depthReplacing = true; }
bool isDepthReplacing() const { return depthReplacing; }
bool setLocalSize(int dim, int size)
@ -474,6 +596,11 @@ public:
return true;
}
unsigned int getLocalSize(int dim) const { return localSize[dim]; }
bool isLocalSizeSet() const
{
// Return true if any component has been set (i.e. any component is not default).
return localSizeNotDefault[0] || localSizeNotDefault[1] || localSizeNotDefault[2];
}
bool setLocalSizeSpecId(int dim, int id)
{
if (localSizeSpecId[dim] != TQualifier::layoutNotSet)
@ -482,6 +609,13 @@ public:
return true;
}
int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; }
bool isLocalSizeSpecialized() const
{
// Return true if any component has been specialized.
return localSizeSpecId[0] != TQualifier::layoutNotSet ||
localSizeSpecId[1] != TQualifier::layoutNotSet ||
localSizeSpecId[2] != TQualifier::layoutNotSet;
}
#ifdef GLSLANG_WEB
void output(TInfoSink&, bool tree) { }
@ -500,7 +634,7 @@ public:
bool getAutoMapBindings() const { return false; }
bool getAutoMapLocations() const { return false; }
int getNumPushConstants() const { return 0; }
void addShaderRecordNVCount() { }
void addShaderRecordCount() { }
void addTaskNVCount() { }
void setUseVulkanMemoryModel() { }
bool usingVulkanMemoryModel() const { return false; }
@ -617,7 +751,7 @@ public:
void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; }
int getNumPushConstants() const { return numPushConstants; }
void addShaderRecordNVCount() { ++numShaderRecordNVBlocks; }
void addShaderRecordCount() { ++numShaderRecordBlocks; }
void addTaskNVCount() { ++numTaskNVBlocks; }
bool setInvocations(int i)
@ -700,6 +834,8 @@ public:
bool getOriginUpperLeft() const { return originUpperLeft; }
void setPixelCenterInteger() { pixelCenterInteger = true; }
bool getPixelCenterInteger() const { return pixelCenterInteger; }
void setTexCoordRedeclared() { texCoordBuiltinRedeclared = true; }
bool getTexCoordRedeclared() const { return texCoordBuiltinRedeclared; }
void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); }
unsigned int getBlendEquations() const { return blendEquations; }
bool setXfbBufferStride(int buffer, unsigned stride)
@ -720,6 +856,8 @@ public:
void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; }
bool hasLayoutDerivativeModeNone() const { return computeDerivativeMode != LayoutDerivativeNone; }
ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; }
void setLayoutPrimitiveCulling() { layoutPrimitiveCulling = true; }
bool getLayoutPrimitiveCulling() const { return layoutPrimitiveCulling; }
bool setPrimitives(int m)
{
if (primitives != TQualifier::layoutNotSet)
@ -756,8 +894,34 @@ public:
void setBinaryDoubleOutput() { binaryDoubleOutput = true; }
bool getBinaryDoubleOutput() { return binaryDoubleOutput; }
void setSubgroupUniformControlFlow() { subgroupUniformControlFlow = true; }
bool getSubgroupUniformControlFlow() const { return subgroupUniformControlFlow; }
// GL_EXT_spirv_intrinsics
void insertSpirvRequirement(const TSpirvRequirement* spirvReq);
bool hasSpirvRequirement() const { return spirvRequirement != nullptr; }
const TSpirvRequirement& getSpirvRequirement() const { return *spirvRequirement; }
void insertSpirvExecutionMode(int executionMode, const TIntermAggregate* args = nullptr);
void insertSpirvExecutionModeId(int executionMode, const TIntermAggregate* args);
bool hasSpirvExecutionMode() const { return spirvExecutionMode != nullptr; }
const TSpirvExecutionMode& getSpirvExecutionMode() const { return *spirvExecutionMode; }
#endif // GLSLANG_WEB
void addBlockStorageOverride(const char* nameStr, TBlockStorageClass backing)
{
std::string name(nameStr);
blockBackingOverrides[name] = backing;
}
TBlockStorageClass getBlockStorageOverride(const char* nameStr) const
{
std::string name = nameStr;
auto pos = blockBackingOverrides.find(name);
if (pos == blockBackingOverrides.end())
return EbsNone;
else
return pos->second;
}
#ifdef ENABLE_HLSL
void setHlslFunctionality1() { hlslFunctionality1 = true; }
bool getHlslFunctionality1() const { return hlslFunctionality1; }
@ -781,10 +945,27 @@ public:
bool usingHlslIoMapping() { return false; }
#endif
bool usingScalarBlockLayout() const {
for (auto extIt = requestedExtensions.begin(); extIt != requestedExtensions.end(); ++extIt) {
if (*extIt == E_GL_EXT_scalar_block_layout)
return true;
}
return false;
}
bool IsRequestedExtension(const char* extension) const
{
return (requestedExtensions.find(extension) != requestedExtensions.end());
}
void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee);
void merge(TInfoSink&, TIntermediate&);
void finalCheck(TInfoSink&, bool keepUncalled);
void mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit, bool mergeExistingOnly);
void mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit);
void checkStageIO(TInfoSink&, TIntermediate&);
bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const;
TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const;
@ -793,6 +974,7 @@ public:
int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision);
int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision);
int checkLocationRT(int set, int location);
int addUsedOffsets(int binding, int offset, int numOffsets);
bool addUsedConstantId(int id);
static int computeTypeLocationSize(const TType&, EShLanguage);
@ -807,6 +989,8 @@ public:
static int getOffset(const TType& type, int index);
static int getBlockSize(const TType& blockType);
static int computeBufferReferenceTypeSize(const TType&);
static bool isIoResizeArray(const TType& type, EShLanguage language);
bool promote(TIntermOperator*);
void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; }
bool getNanMinMaxClamp() const { return nanMinMaxClamp; }
@ -825,47 +1009,53 @@ public:
void addProcess(const std::string& process) { processes.addProcess(process); }
void addProcessArgument(const std::string& arg) { processes.addArgument(arg); }
const std::vector<std::string>& getProcesses() const { return processes.getProcesses(); }
unsigned long long getUniqueId() const { return uniqueId; }
void setUniqueId(unsigned long long id) { uniqueId = id; }
// Certain explicit conversions are allowed conditionally
#ifdef GLSLANG_WEB
bool getArithemeticInt8Enabled() const { return false; }
bool getArithemeticInt16Enabled() const { return false; }
bool getArithemeticFloat16Enabled() const { return false; }
void updateNumericFeature(TNumericFeatures::feature f, bool on) { }
#else
bool getArithemeticInt8Enabled() const {
return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8);
return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8);
}
bool getArithemeticInt16Enabled() const {
return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_AMD_gpu_shader_int16) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16);
return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
numericFeatures.contains(TNumericFeatures::gpu_shader_int16) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16);
}
bool getArithemeticFloat16Enabled() const {
return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_AMD_gpu_shader_half_float) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16);
return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
numericFeatures.contains(TNumericFeatures::gpu_shader_half_float) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16);
}
void updateNumericFeature(TNumericFeatures::feature f, bool on)
{ on ? numericFeatures.insert(f) : numericFeatures.erase(f); }
#endif
protected:
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
void error(TInfoSink& infoSink, const char*);
void warn(TInfoSink& infoSink, const char*);
TIntermSymbol* addSymbol(long long Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
void error(TInfoSink& infoSink, const char*, EShLanguage unitStage = EShLangCount);
void warn(TInfoSink& infoSink, const char*, EShLanguage unitStage = EShLangCount);
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 seedIdMap(TIdMaps& idMaps, long long& IdShift);
void remapIds(const TIdMaps& idMaps, long long idShift, TIntermediate&);
void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects);
void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects, EShLanguage);
void mergeBlockDefinitions(TInfoSink&, TIntermSymbol* block, TIntermSymbol* unitBlock, TIntermediate* unitRoot);
void mergeImplicitArraySizes(TType&, const TType&);
void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, bool crossStage);
void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, EShLanguage);
void checkCallGraphCycles(TInfoSink&);
void checkCallGraphBodies(TInfoSink&, bool keepUncalled);
void inOutLocationCheck(TInfoSink&);
TIntermAggregate* findLinkerObjects() const;
void sharedBlockCheck(TInfoSink&);
bool userOutputUsed() const;
bool isSpecializationOperation(const TIntermOperator&) const;
bool isNonuniformPropagating(TOperator) const;
@ -878,17 +1068,7 @@ protected:
bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&);
void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root);
bool isConversionAllowed(TOperator op, TIntermTyped* node) const;
std::tuple<TBasicType, TBasicType> getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const;
// JohnK: I think this function should go away.
// This data structure is just a log to pass on to back ends.
// Versioning and extensions are handled in Version.cpp, with a rich
// set of functions for querying stages, versions, extension enable/disabled, etc.
#ifdef GLSLANG_WEB
bool extensionRequested(const char *extension) const { return false; }
#else
bool extensionRequested(const char *extension) const {return requestedExtensions.find(extension) != requestedExtensions.end();}
#endif
std::tuple<TBasicType, TBasicType> getConversionDestinationType(TBasicType type0, TBasicType type1, TOperator op) const;
static const char* getResourceName(TResourceType);
@ -898,23 +1078,39 @@ protected:
typedef std::list<TCall> TGraph;
TGraph callGraph;
#ifdef GLSLANG_ANGLE
const EProfile profile = ECoreProfile;
const int version = 450;
#else
EProfile profile; // source profile
int version; // source version
#endif
SpvVersion spvVersion;
TIntermNode* treeRoot;
std::set<std::string> requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
TBuiltInResource resources;
MustBeAssigned<TBuiltInResource> resources;
int numEntryPoints;
int numErrors;
int numPushConstants;
bool recursive;
bool invertY;
bool dxPositionW;
bool enhancedMsgs;
bool useStorageBuffer;
bool invariantAll;
bool nanMinMaxClamp; // true if desiring min/max/clamp to favor non-NaN over NaN
bool depthReplacing;
int localSize[3];
bool localSizeNotDefault[3];
int localSizeSpecId[3];
unsigned long long uniqueId;
std::string globalUniformBlockName;
std::string atomicCounterBlockName;
unsigned int globalUniformBlockSet;
unsigned int globalUniformBlockBinding;
unsigned int atomicCounterBlockSet;
#ifndef GLSLANG_WEB
public:
const char* const implicitThisName;
@ -928,6 +1124,7 @@ protected:
TLayoutGeometry outputPrimitive;
bool pixelCenterInteger;
bool originUpperLeft;
bool texCoordBuiltinRedeclared;
TVertexSpacing vertexSpacing;
TVertexOrder vertexOrder;
TInterlockOrdering interlockOrdering;
@ -942,10 +1139,11 @@ protected:
bool multiStream;
bool layoutOverrideCoverage;
bool geoPassthroughEXT;
int numShaderRecordNVBlocks;
int numShaderRecordBlocks;
ComputeDerivativeMode computeDerivativeMode;
int primitives;
int numTaskNVBlocks;
bool layoutPrimitiveCulling;
// Base shift values
std::array<unsigned int, EResCount> shiftBinding;
@ -968,17 +1166,26 @@ protected:
bool needToLegalize;
bool binaryDoubleOutput;
bool subgroupUniformControlFlow;
bool usePhysicalStorageBuffer;
TSpirvRequirement* spirvRequirement;
TSpirvExecutionMode* spirvExecutionMode;
std::unordered_map<std::string, int> uniformLocationOverrides;
int uniformLocationBase;
TNumericFeatures numericFeatures;
#endif
std::unordered_map<std::string, TBlockStorageClass> blockBackingOverrides;
std::unordered_set<int> usedConstantId; // specialization constant ids used
std::vector<TOffsetRange> usedAtomics; // sets of bindings used by atomic counters
std::vector<TIoRange> usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers
std::vector<TRange> usedIoRT[2]; // sets of used location, one for rayPayload/rayPayloadIN and other
// for callableData/callableDataIn
// set of names of statically read/written I/O that might need extra checking
std::set<TString> ioAccessed;
// source code of shader, useful as part of debug information
std::string sourceFile;
std::string sourceText;

View file

@ -165,22 +165,31 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
}
}
} else {
// matrix from vector
int count = 0;
const int startIndex = index;
// matrix from vector or scalar
int nodeComps = node->getType().computeNumComponents();
for (int i = startIndex; i < endIndex; i++) {
if (i >= instanceSize)
return;
if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 )
if (nodeComps == 1) {
for (int c = 0; c < matrixCols; ++c) {
for (int r = 0; r < matrixRows; ++r) {
if (r == c)
leftUnionArray[index] = rightUnionArray[0];
else
leftUnionArray[index].setDConst(0.0);
index++;
}
}
} else {
int count = 0;
for (int i = index; i < endIndex; i++) {
if (i >= instanceSize)
return;
// construct the matrix in column-major order, from
// the components provided, in order
leftUnionArray[i] = rightUnionArray[count];
else
leftUnionArray[i].setDConst(0.0);
index++;
if (nodeComps > 1)
index++;
count++;
}
}
}
}

View file

@ -58,7 +58,7 @@ public:
const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink,
bool forwardCompatible, EShMessages messages)
:
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
forwardCompatible(forwardCompatible),
profile(profile),
#endif
@ -101,6 +101,7 @@ public:
void updateExtensionBehavior(int line, const char* const extension, const char* behavior) { }
void updateExtensionBehavior(const char* const extension, TExtensionBehavior) { }
void checkExtensionStage(const TSourceLoc&, const char* const extension) { }
void extensionRequires(const TSourceLoc&, const char* const extension, const char* behavior) { }
void fullIntegerCheck(const TSourceLoc&, const char* op) { }
void doubleCheck(const TSourceLoc&, const char* op) { }
bool float16Arithmetic() { return false; }
@ -115,9 +116,14 @@ public:
bool relaxedErrors() const { return false; }
bool suppressWarnings() const { return true; }
bool isForwardCompatible() const { return false; }
#else
#ifdef GLSLANG_ANGLE
const bool forwardCompatible = true;
const EProfile profile = ECoreProfile;
#else
bool forwardCompatible; // true if errors are to be given for use of deprecated features
EProfile profile; // the declared profile in the shader (core by default)
#endif
bool isEsProfile() const { return profile == EEsProfile; }
void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc);
void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions,
@ -139,6 +145,7 @@ public:
virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[],
const char* featureDesc);
virtual void checkExtensionStage(const TSourceLoc&, const char* const extension);
virtual void extensionRequires(const TSourceLoc&, const char* const extension, const char* behavior);
virtual void fullIntegerCheck(const TSourceLoc&, const char* op);
virtual void unimplemented(const TSourceLoc&, const char* featureDesc);
@ -170,6 +177,7 @@ public:
virtual void vulkanRemoved(const TSourceLoc&, const char* op);
virtual void requireVulkan(const TSourceLoc&, const char* op);
virtual void requireSpv(const TSourceLoc&, const char* op);
virtual void requireSpv(const TSourceLoc&, const char *op, unsigned int version);
#if defined(GLSLANG_WEB) && !defined(GLSLANG_WEB_DEVEL)
@ -221,7 +229,8 @@ public:
TIntermediate& intermediate; // helper for making and hooking up pieces of the parse tree
protected:
TMap<TString, TExtensionBehavior> extensionBehavior; // for each extension string, what its current behavior is set to
TMap<TString, TExtensionBehavior> extensionBehavior; // for each extension string, what its current behavior is
TMap<TString, unsigned int> extensionMinSpv; // for each extension string, store minimum spirv required
EShMessages messages; // errors/warnings/rule-sets
int numErrors; // number of compile-time errors encountered
TInputScanner* currentScanner;

View file

@ -422,10 +422,10 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
if (! parseContext.isReadingHLSL() && isMacroInput()) {
if (parseContext.relaxedErrors())
parseContext.ppWarn(ppToken->loc, "nonportable when expanded from macros for preprocessor expression",
"defined", "");
"defined", "");
else
parseContext.ppError(ppToken->loc, "cannot use in preprocessor expression when expanded from macros",
"defined", "");
"defined", "");
}
bool needclose = 0;
token = scanToken(ppToken);
@ -455,6 +455,7 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
token = scanToken(ppToken);
}
} else {
token = tokenPaste(token, *ppToken);
token = evalToToken(token, shortCircuit, res, err, ppToken);
return eval(token, precedence, shortCircuit, res, err, ppToken);
}
@ -621,14 +622,25 @@ int TPpContext::CPPinclude(TPpToken* ppToken)
{
const TSourceLoc directiveLoc = ppToken->loc;
bool startWithLocalSearch = true; // to additionally include the extra "" paths
int token = scanToken(ppToken);
int token;
// handle <header-name>-style #include
if (token == '<') {
// Find the first non-whitespace char after #include
int ch = getChar();
while (ch == ' ' || ch == '\t') {
ch = getChar();
}
if (ch == '<') {
// <header-name> style
startWithLocalSearch = false;
token = scanHeaderName(ppToken, '>');
} else if (ch == '"') {
// "header-name" style
token = scanHeaderName(ppToken, '"');
} else {
// unexpected, get the full token to generate the error
ungetChar();
token = scanToken(ppToken);
}
// otherwise ppToken already has the header name and it was "header-name" style
if (token != PpAtomConstString) {
parseContext.ppError(directiveLoc, "must be followed by a header name", "#include", "");
@ -711,7 +723,9 @@ int TPpContext::CPPline(TPpToken* ppToken)
const char* sourceName = nullptr; // Optional source file name.
bool lineErr = false;
bool fileErr = false;
disableEscapeSequences = true;
token = eval(token, MIN_PRECEDENCE, false, lineRes, lineErr, ppToken);
disableEscapeSequences = false;
if (! lineErr) {
lineToken = lineRes;
if (token == '\n')
@ -754,7 +768,9 @@ int TPpContext::CPPline(TPpToken* ppToken)
// Handle #error
int TPpContext::CPPerror(TPpToken* ppToken)
{
disableEscapeSequences = true;
int token = scanToken(ppToken);
disableEscapeSequences = false;
std::string message;
TSourceLoc loc = ppToken->loc;
@ -1169,7 +1185,9 @@ MacroExpandResult TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, b
int macroAtom = atomStrings.getAtom(ppToken->name);
switch (macroAtom) {
case PpAtomLineMacro:
ppToken->ival = parseContext.getCurrentLoc().line;
// Arguments which are macro have been replaced in the first stage.
if (ppToken->ival == 0)
ppToken->ival = parseContext.getCurrentLoc().line;
snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival);
UngetToken(PpAtomConstInt, ppToken);
return MacroExpandStarted;
@ -1270,6 +1288,11 @@ MacroExpandResult TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, b
nestStack.push_back('}');
else if (nestStack.size() > 0 && token == nestStack.back())
nestStack.pop_back();
//Macro replacement list is expanded in the last stage.
if (atomStrings.getAtom(ppToken->name) == PpAtomLineMacro)
ppToken->ival = parseContext.getCurrentLoc().line;
in->args[arg]->putToken(token, ppToken);
tokenRecorded = true;
}

View file

@ -87,7 +87,8 @@ namespace glslang {
TPpContext::TPpContext(TParseContextBase& pc, const std::string& rootFileName, TShader::Includer& inclr) :
preamble(0), strings(0), previous_token('\n'), parseContext(pc), includer(inclr), inComment(false),
rootFileName(rootFileName),
currentSourceFile(rootFileName)
currentSourceFile(rootFileName),
disableEscapeSequences(false)
{
ifdepth = 0;
for (elsetracker = 0; elsetracker < maxIfNesting; elsetracker++)

View file

@ -105,13 +105,13 @@ public:
}
// Used for comparing macro definitions, so checks what is relevant for that.
bool operator==(const TPpToken& right)
bool operator==(const TPpToken& right) const
{
return space == right.space &&
ival == right.ival && dval == right.dval && i64val == right.i64val &&
strncmp(name, right.name, MaxTokenLength) == 0;
}
bool operator!=(const TPpToken& right) { return ! operator==(right); }
bool operator!=(const TPpToken& right) const { return ! operator==(right); }
TSourceLoc loc;
// True if a space (for white space or a removed comment) should also be
@ -695,6 +695,7 @@ protected:
std::string currentSourceFile;
std::istringstream strtodStream;
bool disableEscapeSequences;
};
} // end namespace glslang

View file

@ -1026,12 +1026,80 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
case '\'':
return pp->characterLiteral(ppToken);
case '"':
// TODO: If this gets enhanced to handle escape sequences, or
// anything that is different than what #include needs, then
// #include needs to use scanHeaderName() for this.
// #include uses scanHeaderName() to ignore these escape sequences.
ch = getch();
while (ch != '"' && ch != '\n' && ch != EndOfInput) {
if (len < MaxTokenLength) {
if (ch == '\\' && !pp->disableEscapeSequences) {
int nextCh = getch();
switch (nextCh) {
case '\'': ch = 0x27; break;
case '"': ch = 0x22; break;
case '?': ch = 0x3f; break;
case '\\': ch = 0x5c; break;
case 'a': ch = 0x07; break;
case 'b': ch = 0x08; break;
case 'f': ch = 0x0c; break;
case 'n': ch = 0x0a; break;
case 'r': ch = 0x0d; break;
case 't': ch = 0x09; break;
case 'v': ch = 0x0b; break;
case 'x':
// Hex value, arbitrary number of characters. Terminated by the first
// non-hex digit
{
int numDigits = 0;
ch = 0;
while (true) {
nextCh = getch();
if (nextCh >= '0' && nextCh <= '9')
nextCh -= '0';
else if (nextCh >= 'A' && nextCh <= 'F')
nextCh -= 'A' - 10;
else if (nextCh >= 'a' && nextCh <= 'f')
nextCh -= 'a' - 10;
else {
ungetch();
break;
}
numDigits++;
ch = ch * 0x10 + nextCh;
}
if (numDigits == 0) {
pp->parseContext.ppError(ppToken->loc, "Expected hex value in escape sequence", "string", "");
}
break;
}
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
// Octal value, up to three octal digits
{
int numDigits = 1;
ch = nextCh - '0';
while (numDigits < 3) {
nextCh = getch();
if (nextCh >= '0' && nextCh <= '7')
nextCh -= '0';
else {
ungetch();
break;
}
numDigits++;
ch = ch * 8 + nextCh;
}
break;
}
default:
pp->parseContext.ppError(ppToken->loc, "Invalid escape sequence", "string", "");
break;
}
}
ppToken->name[len] = (char)ch;
len++;
ch = getch();
@ -1120,10 +1188,14 @@ int TPpContext::tokenize(TPpToken& ppToken)
continue;
break;
case PpAtomConstString:
// HLSL allows string literals.
// GLSL allows string literals with GL_EXT_debug_printf.
if (ifdepth == 0 && parseContext.intermediate.getSource() != EShSourceHlsl) {
// HLSL allows string literals.
parseContext.ppError(ppToken.loc, "string literals not supported", "\"\"", "");
continue;
const char* const string_literal_EXTs[] = { E_GL_EXT_debug_printf, E_GL_EXT_spirv_intrinsics };
parseContext.requireExtensions(ppToken.loc, 2, string_literal_EXTs, "string literal");
if (!parseContext.extensionTurnedOn(E_GL_EXT_debug_printf) &&
!parseContext.extensionTurnedOn(E_GL_EXT_spirv_intrinsics))
continue;
}
break;
case '\'':

View file

@ -33,7 +33,7 @@
// POSSIBILITY OF SUCH DAMAGE.
//
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
#include "../Include/Common.h"
#include "reflection.h"
@ -77,10 +77,10 @@ namespace glslang {
// This is in the glslang namespace directly so it can be a friend of TReflection.
//
class TReflectionTraverser : public TLiveTraverser {
class TReflectionTraverser : public TIntermTraverser {
public:
TReflectionTraverser(const TIntermediate& i, TReflection& r) :
TLiveTraverser(i), reflection(r) { }
TIntermTraverser(), intermediate(i), reflection(r), updateStageMasks(true) { }
virtual bool visitBinary(TVisit, TIntermBinary* node);
virtual void visitSymbol(TIntermSymbol* base);
@ -92,11 +92,28 @@ public:
if (processedDerefs.find(&base) == processedDerefs.end()) {
processedDerefs.insert(&base);
int blockIndex = -1;
int offset = -1;
TList<TIntermBinary*> derefs;
TString baseName = base.getName();
if (base.getType().getBasicType() == EbtBlock) {
offset = 0;
bool anonymous = IsAnonymous(baseName);
const TString& blockName = base.getType().getTypeName();
if (!anonymous)
baseName = blockName;
else
baseName = "";
blockIndex = addBlockName(blockName, base.getType(), intermediate.getBlockSize(base.getType()));
}
// Use a degenerate (empty) set of dereferences to immediately put as at the end of
// the dereference change expected by blowUpActiveAggregate.
TList<TIntermBinary*> derefs;
blowUpActiveAggregate(base.getType(), base.getName(), derefs, derefs.end(), -1, -1, 0, 0,
base.getQualifier().storage, true);
blowUpActiveAggregate(base.getType(), baseName, derefs, derefs.end(), offset, blockIndex, 0, -1, 0,
base.getQualifier().storage, updateStageMasks);
}
}
@ -155,9 +172,9 @@ public:
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())
@ -233,7 +250,7 @@ public:
// A value of 0 for arraySize will mean to use the full array's size.
void blowUpActiveAggregate(const TType& baseType, const TString& baseName, const TList<TIntermBinary*>& derefs,
TList<TIntermBinary*>::const_iterator deref, int offset, int blockIndex, int arraySize,
int topLevelArrayStride, TStorageQualifier baseStorage, bool active)
int topLevelArraySize, int topLevelArrayStride, TStorageQualifier baseStorage, bool active)
{
// when strictArraySuffix is enabled, we closely follow the rules from ARB_program_interface_query.
// Broadly:
@ -262,14 +279,15 @@ public:
// 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) {
TString newBaseName = name;
if (strictArraySuffix && blockParent)
if (terminalType->getBasicType() == EbtBlock) {}
else if (strictArraySuffix && blockParent)
newBaseName.append(TString("[0]"));
else if (strictArraySuffix || baseType.getBasicType() != EbtBlock)
newBaseName.append(TString("[") + String(i) + "]");
TList<TIntermBinary*>::const_iterator nextDeref = deref;
++nextDeref;
blowUpActiveAggregate(*terminalType, newBaseName, derefs, nextDeref, offset, blockIndex, arraySize,
topLevelArrayStride, baseStorage, active);
topLevelArraySize, topLevelArrayStride, baseStorage, active);
if (offset >= 0)
offset += stride;
@ -282,9 +300,10 @@ public:
int stride = getArrayStride(baseType, visitNode->getLeft()->getType());
index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
if (strictArraySuffix && blockParent) {
if (terminalType->getBasicType() == EbtBlock) {}
else if (strictArraySuffix && blockParent)
name.append(TString("[0]"));
} else if (strictArraySuffix || baseType.getBasicType() != EbtBlock) {
else if (strictArraySuffix || baseType.getBasicType() != EbtBlock) {
name.append(TString("[") + String(index) + "]");
if (offset >= 0)
@ -294,7 +313,10 @@ public:
if (topLevelArrayStride == 0)
topLevelArrayStride = stride;
blockParent = false;
// expand top-level arrays in blocks with [0] suffix
if (topLevelArrayStride != 0 && visitNode->getLeft()->getType().isArray()) {
blockParent = false;
}
break;
}
case EOpIndexDirectStruct:
@ -304,6 +326,12 @@ public:
if (name.size() > 0)
name.append(".");
name.append((*visitNode->getLeft()->getType().getStruct())[index].type->getFieldName());
// expand non top-level arrays with [x] suffix
if (visitNode->getLeft()->getType().getBasicType() != EbtBlock && terminalType->isArray())
{
blockParent = false;
}
break;
default:
break;
@ -323,24 +351,27 @@ public:
if (offset >= 0)
stride = getArrayStride(baseType, *terminalType);
if (topLevelArrayStride == 0)
topLevelArrayStride = stride;
int arrayIterateSize = std::max(terminalType->getOuterArraySize(), 1);
// for top-level arrays in blocks, only expand [0] to avoid explosion of items
if (strictArraySuffix && blockParent)
if ((strictArraySuffix && blockParent) ||
((topLevelArraySize == arrayIterateSize) && (topLevelArrayStride == 0))) {
arrayIterateSize = 1;
}
if (topLevelArrayStride == 0)
topLevelArrayStride = stride;
for (int i = 0; i < arrayIterateSize; ++i) {
TString newBaseName = name;
newBaseName.append(TString("[") + String(i) + "]");
if (terminalType->getBasicType() != EbtBlock)
newBaseName.append(TString("[") + String(i) + "]");
TType derefType(*terminalType, 0);
if (offset >= 0)
offset = baseOffset + stride * i;
blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0,
topLevelArrayStride, baseStorage, active);
topLevelArraySize, topLevelArrayStride, baseStorage, active);
}
} else {
// Visit all members of this aggregate, and for each one,
@ -369,8 +400,31 @@ public:
arrayStride = getArrayStride(baseType, derefType);
}
blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0,
arrayStride, baseStorage, active);
if (topLevelArraySize == -1 && arrayStride == 0 && blockParent)
topLevelArraySize = 1;
if (strictArraySuffix && blockParent) {
// if this member is an array, store the top-level array stride but start the explosion from
// the inner struct type.
if (derefType.isArray() && derefType.isStruct()) {
newBaseName.append("[0]");
auto dimSize = derefType.isUnsizedArray() ? 0 : derefType.getArraySizes()->getDimSize(0);
blowUpActiveAggregate(TType(derefType, 0), newBaseName, derefs, derefs.end(), memberOffsets[i],
blockIndex, 0, dimSize, arrayStride, terminalType->getQualifier().storage, false);
}
else if (derefType.isArray()) {
auto dimSize = derefType.isUnsizedArray() ? 0 : derefType.getArraySizes()->getDimSize(0);
blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), memberOffsets[i], blockIndex,
0, dimSize, 0, terminalType->getQualifier().storage, false);
}
else {
blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), memberOffsets[i], blockIndex,
0, 1, 0, terminalType->getQualifier().storage, false);
}
} else {
blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0,
topLevelArraySize, arrayStride, baseStorage, active);
}
}
}
@ -406,6 +460,7 @@ public:
if ((reflection.options & EShReflectionSeparateBuffers) && terminalType->isAtomic())
reflection.atomicCounterUniformIndices.push_back(uniformIndex);
variables.back().topLevelArraySize = topLevelArraySize;
variables.back().topLevelArrayStride = topLevelArrayStride;
if ((reflection.options & EShReflectionAllBlockVariables) && active) {
@ -537,65 +592,17 @@ public:
if (! anonymous)
baseName = blockName;
if (base->getType().isArray()) {
TType derefType(base->getType(), 0);
assert(! anonymous);
for (int e = 0; e < base->getType().getCumulativeArraySize(); ++e)
blockIndex = addBlockName(blockName + "[" + String(e) + "]", derefType,
intermediate.getBlockSize(base->getType()));
baseName.append(TString("[0]"));
} else
blockIndex = addBlockName(blockName, base->getType(), intermediate.getBlockSize(base->getType()));
blockIndex = addBlockName(blockName, base->getType(), intermediate.getBlockSize(base->getType()));
if (reflection.options & EShReflectionAllBlockVariables) {
// Use a degenerate (empty) set of dereferences to immediately put as at the end of
// the dereference change expected by blowUpActiveAggregate.
TList<TIntermBinary*> derefs;
// because we don't have any derefs, the first thing blowUpActiveAggregate will do is iterate over each
// member in the struct definition. This will lose any information about whether the parent was a buffer
// block. So if we're using strict array rules which don't expand the first child of a buffer block we
// instead iterate over the children here.
const bool strictArraySuffix = (reflection.options & EShReflectionStrictArraySuffix);
bool blockParent = (base->getType().getBasicType() == EbtBlock && base->getQualifier().storage == EvqBuffer);
if (strictArraySuffix && blockParent) {
TType structDerefType(base->getType(), 0);
const TType &structType = base->getType().isArray() ? structDerefType : base->getType();
const TTypeList& typeList = *structType.getStruct();
TVector<int> memberOffsets;
memberOffsets.resize(typeList.size());
getOffsets(structType, memberOffsets);
for (int i = 0; i < (int)typeList.size(); ++i) {
TType derefType(structType, i);
TString name = baseName;
if (name.size() > 0)
name.append(".");
name.append(typeList[i].type->getFieldName());
// if this member is an array, store the top-level array stride but start the explosion from
// the inner struct type.
if (derefType.isArray() && derefType.isStruct()) {
name.append("[0]");
blowUpActiveAggregate(TType(derefType, 0), name, derefs, derefs.end(), memberOffsets[i],
blockIndex, 0, getArrayStride(structType, derefType),
base->getQualifier().storage, false);
} else {
blowUpActiveAggregate(derefType, name, derefs, derefs.end(), memberOffsets[i], blockIndex,
0, 0, base->getQualifier().storage, false);
}
}
} else {
// otherwise - if we're not using strict array suffix rules, or this isn't a block so we are
// expanding root arrays anyway, just start the iteration from the base block type.
blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.end(), 0, blockIndex, 0, 0,
// otherwise - if we're not using strict array suffix rules, or this isn't a block so we are
// expanding root arrays anyway, just start the iteration from the base block type.
blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.end(), 0, blockIndex, 0, -1, 0,
base->getQualifier().storage, false);
}
}
}
@ -626,30 +633,43 @@ public:
else
baseName = base->getName();
}
blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.begin(), offset, blockIndex, arraySize, 0,
blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.begin(), offset, blockIndex, arraySize, -1, 0,
base->getQualifier().storage, true);
}
int addBlockName(const TString& name, const TType& type, int size)
{
TReflection::TMapIndexToReflection& blocks = reflection.GetBlockMapForStorage(type.getQualifier().storage);
int blockIndex;
TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str());
if (reflection.nameToIndex.find(name.c_str()) == reflection.nameToIndex.end()) {
blockIndex = (int)blocks.size();
reflection.nameToIndex[name.c_str()] = blockIndex;
blocks.push_back(TObjectReflection(name.c_str(), type, -1, -1, size, -1));
blocks.back().numMembers = countAggregateMembers(type);
EShLanguageMask& stages = blocks.back().stages;
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
int blockIndex = 0;
if (type.isArray()) {
TType derefType(type, 0);
for (int e = 0; e < type.getOuterArraySize(); ++e) {
int memberBlockIndex = addBlockName(name + "[" + String(e) + "]", derefType, size);
if (e == 0)
blockIndex = memberBlockIndex;
}
} else {
blockIndex = it->second;
TReflection::TMapIndexToReflection& blocks = reflection.GetBlockMapForStorage(type.getQualifier().storage);
EShLanguageMask& stages = blocks[blockIndex].stages;
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str());
if (reflection.nameToIndex.find(name.c_str()) == reflection.nameToIndex.end()) {
blockIndex = (int)blocks.size();
reflection.nameToIndex[name.c_str()] = blockIndex;
blocks.push_back(TObjectReflection(name.c_str(), type, -1, -1, size, blockIndex));
blocks.back().numMembers = countAggregateMembers(type);
if (updateStageMasks) {
EShLanguageMask& stages = blocks.back().stages;
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
}
}
else {
blockIndex = it->second;
if (updateStageMasks) {
EShLanguageMask& stages = blocks[blockIndex].stages;
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
}
}
}
return blockIndex;
@ -887,8 +907,8 @@ public:
case EbtFloat16: return GL_FLOAT16_VEC2_NV + offset;
case EbtInt: return GL_INT_VEC2 + offset;
case EbtUint: return GL_UNSIGNED_INT_VEC2 + offset;
case EbtInt64: return GL_INT64_ARB + offset;
case EbtUint64: return GL_UNSIGNED_INT64_ARB + offset;
case EbtInt64: return GL_INT64_VEC2_ARB + offset;
case EbtUint64: return GL_UNSIGNED_INT64_VEC2_ARB + offset;
case EbtBool: return GL_BOOL_VEC2 + offset;
case EbtAtomicUint: return GL_UNSIGNED_INT_ATOMIC_COUNTER + offset;
default: return 0;
@ -995,8 +1015,10 @@ public:
return type.isArray() ? type.getOuterArraySize() : 1;
}
const TIntermediate& intermediate;
TReflection& reflection;
std::set<const TIntermNode*> processedDerefs;
bool updateStageMasks;
protected:
TReflectionTraverser(TReflectionTraverser&);
@ -1029,7 +1051,21 @@ bool TReflectionTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
// To reflect non-dereferenced objects.
void TReflectionTraverser::visitSymbol(TIntermSymbol* base)
{
if (base->getQualifier().storage == EvqUniform)
if (base->getQualifier().storage == EvqUniform) {
if (base->getBasicType() == EbtBlock) {
if (reflection.options & EShReflectionSharedStd140UBO) {
addUniform(*base);
}
} else {
addUniform(*base);
}
}
// #TODO add std140/layout active rules for ssbo, same with ubo.
// Storage buffer blocks will be collected and expanding in this part.
if((reflection.options & EShReflectionSharedStd140SSBO) &&
(base->getQualifier().storage == EvqBuffer && base->getBasicType() == EbtBlock &&
(base->getQualifier().layoutPacking == ElpStd140 || base->getQualifier().layoutPacking == ElpShared)))
addUniform(*base);
if ((intermediate.getStage() == reflection.firstStage && base->getQualifier().isPipeInput()) ||
@ -1102,6 +1138,8 @@ void TReflection::buildCounterIndices(const TIntermediate& intermediate)
if (index >= 0)
indexToUniformBlock[i].counterIndex = index;
}
#else
(void)intermediate;
#endif
}
@ -1135,15 +1173,47 @@ bool TReflection::addStage(EShLanguage stage, const TIntermediate& intermediate)
TReflectionTraverser it(intermediate, *this);
// put the entry point on the list of functions to process
it.pushFunction(intermediate.getEntryPointMangledName().c_str());
// process all the functions
while (! it.functions.empty()) {
TIntermNode* function = it.functions.back();
it.functions.pop_back();
function->traverse(&it);
for (auto& sequnence : intermediate.getTreeRoot()->getAsAggregate()->getSequence()) {
if (sequnence->getAsAggregate() != nullptr) {
if (sequnence->getAsAggregate()->getOp() == glslang::EOpLinkerObjects) {
it.updateStageMasks = false;
TIntermAggregate* linkerObjects = sequnence->getAsAggregate();
for (auto& sequnence : linkerObjects->getSequence()) {
auto pNode = sequnence->getAsSymbolNode();
if (pNode != nullptr) {
if ((pNode->getQualifier().storage == EvqUniform &&
(options & EShReflectionSharedStd140UBO)) ||
(pNode->getQualifier().storage == EvqBuffer &&
(options & EShReflectionSharedStd140SSBO))) {
// collect std140 and shared uniform block form AST
if ((pNode->getBasicType() == EbtBlock) &&
((pNode->getQualifier().layoutPacking == ElpStd140) ||
(pNode->getQualifier().layoutPacking == ElpShared))) {
pNode->traverse(&it);
}
}
else if ((options & EShReflectionAllIOVariables) &&
(pNode->getQualifier().isPipeInput() || pNode->getQualifier().isPipeOutput()))
{
pNode->traverse(&it);
}
}
}
} else {
// This traverser will travers all function in AST.
// If we want reflect uncalled function, we need set linke message EShMsgKeepUncalled.
// When EShMsgKeepUncalled been set to true, all function will be keep in AST, even it is a uncalled function.
// This will keep some uniform variables in reflection, if those uniform variables is used in these uncalled function.
//
// If we just want reflect only live node, we can use a default link message or set EShMsgKeepUncalled false.
// When linke message not been set EShMsgKeepUncalled, linker won't keep uncalled function in AST.
// So, travers all function node can equivalent to travers live function.
it.updateStageMasks = true;
sequnence->getAsAggregate()->traverse(&it);
}
}
}
it.updateStageMasks = true;
buildCounterIndices(intermediate);
buildUniformStageMask(intermediate);
@ -1188,7 +1258,7 @@ void TReflection::dump()
for (int dim=0; dim<3; ++dim)
if (getLocalSize(dim) > 1)
printf("Local size %s: %d\n", axis[dim], getLocalSize(dim));
printf("Local size %s: %u\n", axis[dim], getLocalSize(dim));
printf("\n");
}
@ -1201,4 +1271,4 @@ void TReflection::dump()
} // end namespace glslang
#endif // GLSLANG_WEB
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE

View file

@ -33,7 +33,7 @@
// POSSIBILITY OF SUCH DAMAGE.
//
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
#ifndef _REFLECTION_INCLUDED
#define _REFLECTION_INCLUDED
@ -220,4 +220,4 @@ protected:
#endif // _REFLECTION_INCLUDED
#endif // GLSLANG_WEB
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE

View file

@ -1,3 +1,36 @@
# Copyright (C) 2020 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 The Khronos Group Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
add_library(OSDependent STATIC ossource.cpp ../osinclude.h)
set_property(TARGET OSDependent PROPERTY FOLDER glslang)
set_property(TARGET OSDependent PROPERTY POSITION_INDEPENDENT_CODE ON)
@ -23,4 +56,4 @@ if(ENABLE_GLSLANG_INSTALL)
install(TARGETS OSDependent EXPORT OSDependentTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(EXPORT OSDependentTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
endif(ENABLE_GLSLANG_INSTALL)
endif()

View file

@ -172,7 +172,7 @@ namespace {
pthread_mutex_t gMutex;
}
void InitGlobalLock()
static void InitMutex(void)
{
pthread_mutexattr_t mutexattr;
pthread_mutexattr_init(&mutexattr);
@ -180,6 +180,12 @@ void InitGlobalLock()
pthread_mutex_init(&gMutex, &mutexattr);
}
void InitGlobalLock()
{
static pthread_once_t once = PTHREAD_ONCE_INIT;
pthread_once(&once, InitMutex);
}
void GetGlobalLock()
{
pthread_mutex_lock(&gMutex);

View file

@ -1,24 +1,71 @@
add_executable(glslang.js "glslang.js.cpp")
glslang_set_link_args(glslang.js)
target_link_libraries(glslang.js glslang SPIRV)
if(EMSCRIPTEN)
set_target_properties(glslang.js PROPERTIES
OUTPUT_NAME "glslang"
SUFFIX ".js")
em_link_pre_js(glslang.js "${CMAKE_CURRENT_SOURCE_DIR}/glslang.pre.js")
# Copyright (C) 2020 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 The Khronos Group Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
target_link_options(glslang.js PRIVATE
"SHELL:--bind -s MODULARIZE=1")
if(ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE)
target_link_options(glslang.js PRIVATE
"SHELL:-s ENVIRONMENT=node -s BINARYEN_ASYNC_COMPILATION=0")
else()
target_link_options(glslang.js PRIVATE
"SHELL:-s ENVIRONMENT=web,worker")
endif()
if(ENABLE_GLSLANG_JS)
add_executable(glslang.js "glslang.js.cpp")
glslang_set_link_args(glslang.js)
target_link_libraries(glslang.js glslang SPIRV)
if(NOT ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE)
add_custom_command(TARGET glslang.js POST_BUILD
COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/glslang.after.js >> ${CMAKE_CURRENT_BINARY_DIR}/glslang.js)
# Link library names that start with "-" are treated as link flags.
# "-Os" should be OK in MSVC; don't use /Os because CMake won't
# treat it as a link flag.
target_link_libraries(glslang.js "-Os")
if(EMSCRIPTEN)
set_target_properties(glslang.js PROPERTIES
OUTPUT_NAME "glslang"
SUFFIX ".js")
em_link_pre_js(glslang.js "${CMAKE_CURRENT_SOURCE_DIR}/glslang.pre.js")
target_link_libraries(glslang.js "--llvm-lto 1")
target_link_libraries(glslang.js "--closure 1")
target_link_libraries(glslang.js "-s MODULARIZE=1")
target_link_libraries(glslang.js "-s ALLOW_MEMORY_GROWTH=1")
target_link_libraries(glslang.js "-s FILESYSTEM=0")
if(ENABLE_EMSCRIPTEN_SINGLE_FILE)
target_link_libraries(glslang.js "-s SINGLE_FILE=1")
endif()
if(ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE)
target_link_libraries(glslang.js "-s ENVIRONMENT=node -s BINARYEN_ASYNC_COMPILATION=0")
else()
target_link_libraries(glslang.js "-s ENVIRONMENT=web,worker")
endif()
if(NOT ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE)
add_custom_command(TARGET glslang.js POST_BUILD
COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/glslang.after.js >> ${CMAKE_CURRENT_BINARY_DIR}/glslang.js)
endif()
endif()
endif(EMSCRIPTEN)
endif()

View file

@ -141,6 +141,7 @@ const TBuiltInResource DefaultTBuiltInResource = {
/* .maxTaskWorkGroupSizeY_NV = */ 1,
/* .maxTaskWorkGroupSizeZ_NV = */ 1,
/* .maxMeshViewCountNV = */ 4,
/* .maxDualSourceDrawBuffersEXT = */ 1,
/* .limits = */ {
/* .nonInductiveForLoops = */ 1,
@ -176,7 +177,12 @@ extern "C" {
* If null, the compilation failed.
*/
EMSCRIPTEN_KEEPALIVE
void* convert_glsl_to_spirv(const char* glsl, int stage_int, bool gen_debug, uint32_t** spirv, size_t* spirv_len)
void* convert_glsl_to_spirv(const char* glsl,
int stage_int,
bool gen_debug,
glslang::EShTargetLanguageVersion spirv_version,
uint32_t** spirv,
size_t* spirv_len)
{
if (glsl == nullptr) {
fprintf(stderr, "Input pointer null\n");
@ -194,6 +200,18 @@ void* convert_glsl_to_spirv(const char* glsl, int stage_int, bool gen_debug, uin
return nullptr;
}
EShLanguage stage = static_cast<EShLanguage>(stage_int);
switch (spirv_version) {
case glslang::EShTargetSpv_1_0:
case glslang::EShTargetSpv_1_1:
case glslang::EShTargetSpv_1_2:
case glslang::EShTargetSpv_1_3:
case glslang::EShTargetSpv_1_4:
case glslang::EShTargetSpv_1_5:
break;
default:
fprintf(stderr, "Invalid SPIR-V version number\n");
return nullptr;
}
if (!initialized) {
glslang::InitializeProcess();
@ -203,8 +221,8 @@ void* convert_glsl_to_spirv(const char* glsl, int stage_int, bool gen_debug, uin
glslang::TShader shader(stage);
shader.setStrings(&glsl, 1);
shader.setEnvInput(glslang::EShSourceGlsl, stage, glslang::EShClientVulkan, 100);
shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_1);
shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_3);
shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_0);
shader.setEnvTarget(glslang::EShTargetSpv, spirv_version);
if (!shader.parse(&DefaultTBuiltInResource, 100, true, EShMsgDefault)) {
fprintf(stderr, "Parse failed\n");
fprintf(stderr, "%s\n", shader.getInfoLog());
@ -260,7 +278,7 @@ void main() { })";
uint32_t* output;
size_t output_len;
void* id = convert_glsl_to_spirv(input, 4, false, &output, &output_len);
void* id = convert_glsl_to_spirv(input, 4, false, glslang::EShTargetSpv_1_0, &output, &output_len);
assert(output != nullptr);
assert(output_len != 0);
destroy_output_buffer(id);

View file

@ -1,23 +1,34 @@
Module['compileGLSLZeroCopy'] = function(glsl, shader_stage, gen_debug) {
Module['compileGLSLZeroCopy'] = function(glsl, shader_stage, gen_debug, spirv_version) {
gen_debug = !!gen_debug;
var shader_stage_int;
if (shader_stage === 'vertex') {
shader_stage_int = 0;
} else if (shader_stage === 'fragment') {
shader_stage_int = 4;
} else if (shader_stage === 'compute') {
shader_stage_int = 5;
} else {
throw new Error("shader_stage must be 'vertex', 'fragment', or 'compute'");
var shader_stage_int; // EShLanguage
switch (shader_stage) {
case 'vertex': shader_stage_int = 0; break;
case 'fragment': shader_stage_int = 4; break;
case 'compute': shader_stage_int = 5; break;
default:
throw new Error("shader_stage must be 'vertex', 'fragment', or 'compute'.");
}
spirv_version = spirv_version || '1.0';
var spirv_version_int; // EShTargetLanguageVersion
switch (spirv_version) {
case '1.0': spirv_version_int = (1 << 16) | (0 << 8); break;
case '1.1': spirv_version_int = (1 << 16) | (1 << 8); break;
case '1.2': spirv_version_int = (1 << 16) | (2 << 8); break;
case '1.3': spirv_version_int = (1 << 16) | (3 << 8); break;
case '1.4': spirv_version_int = (1 << 16) | (4 << 8); break;
case '1.5': spirv_version_int = (1 << 16) | (5 << 8); break;
default:
throw new Error("spirv_version must be '1.0' ~ '1.5'.");
}
var p_output = Module['_malloc'](4);
var p_output_len = Module['_malloc'](4);
var id = ccall('convert_glsl_to_spirv',
'number',
['string', 'number', 'boolean', 'number', 'number'],
[glsl, shader_stage_int, gen_debug, p_output, p_output_len]);
['string', 'number', 'boolean', 'number', 'number', 'number'],
[glsl, shader_stage_int, gen_debug, spirv_version_int, p_output, p_output_len]);
var output = getValue(p_output, 'i32');
var output_len = getValue(p_output_len, 'i32');
Module['_free'](p_output);
@ -37,8 +48,8 @@ Module['compileGLSLZeroCopy'] = function(glsl, shader_stage, gen_debug) {
return ret;
};
Module['compileGLSL'] = function(glsl, shader_stage, gen_debug) {
var compiled = Module['compileGLSLZeroCopy'](glsl, shader_stage, gen_debug);
Module['compileGLSL'] = function(glsl, shader_stage, gen_debug, spirv_version) {
var compiled = Module['compileGLSLZeroCopy'](glsl, shader_stage, gen_debug, spirv_version);
var ret = compiled['data'].slice()
compiled['free']();
return ret;

View file

@ -1,3 +1,36 @@
# Copyright (C) 2020 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 The Khronos Group Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
set(SOURCES ossource.cpp ../osinclude.h)
add_library(OSDependent STATIC ${SOURCES})
@ -12,10 +45,10 @@ endif()
if(WIN32)
source_group("Source" FILES ${SOURCES})
endif(WIN32)
endif()
if(ENABLE_GLSLANG_INSTALL)
install(TARGETS OSDependent EXPORT OSDependentTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(EXPORT OSDependentTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
endif(ENABLE_GLSLANG_INSTALL)
endif()

View file

@ -44,16 +44,25 @@
#include <vector>
#ifdef _WIN32
#define C_DECL __cdecl
//#ifdef SH_EXPORTING
// #define SH_IMPORT_EXPORT __declspec(dllexport)
//#else
// #define SH_IMPORT_EXPORT __declspec(dllimport)
//#endif
#define SH_IMPORT_EXPORT
#define C_DECL __cdecl
#else
#define SH_IMPORT_EXPORT
#define C_DECL
#define C_DECL
#endif
#ifdef GLSLANG_IS_SHARED_LIBRARY
#ifdef _WIN32
#ifdef GLSLANG_EXPORTING
#define GLSLANG_EXPORT __declspec(dllexport)
#else
#define GLSLANG_EXPORT __declspec(dllimport)
#endif
#elif __GNUC__ >= 4
#define GLSLANG_EXPORT __attribute__((visibility("default")))
#endif
#endif // GLSLANG_IS_SHARED_LIBRARY
#ifndef GLSLANG_EXPORT
#define GLSLANG_EXPORT
#endif
//
@ -65,22 +74,17 @@
extern "C" {
#endif
// This should always increase, as some paths to do not consume
// a more major number.
// It should increment by one when new functionality is added.
#define GLSLANG_MINOR_VERSION 13
//
// Call before doing any other compiler/linker operations.
//
// (Call once per process, not once per thread.)
//
SH_IMPORT_EXPORT int ShInitialize();
GLSLANG_EXPORT int ShInitialize();
//
// Call this at process shutdown to clean up memory.
//
SH_IMPORT_EXPORT int ShFinalize();
GLSLANG_EXPORT int ShFinalize();
//
// Types of languages the compiler can consume.
@ -92,32 +96,45 @@ typedef enum {
EShLangGeometry,
EShLangFragment,
EShLangCompute,
EShLangRayGenNV,
EShLangIntersectNV,
EShLangAnyHitNV,
EShLangClosestHitNV,
EShLangMissNV,
EShLangCallableNV,
EShLangRayGen,
EShLangRayGenNV = EShLangRayGen,
EShLangIntersect,
EShLangIntersectNV = EShLangIntersect,
EShLangAnyHit,
EShLangAnyHitNV = EShLangAnyHit,
EShLangClosestHit,
EShLangClosestHitNV = EShLangClosestHit,
EShLangMiss,
EShLangMissNV = EShLangMiss,
EShLangCallable,
EShLangCallableNV = EShLangCallable,
EShLangTaskNV,
EShLangMeshNV,
EShLangCount,
LAST_ELEMENT_MARKER(EShLangCount),
} EShLanguage; // would be better as stage, but this is ancient now
typedef enum {
typedef enum : unsigned {
EShLangVertexMask = (1 << EShLangVertex),
EShLangTessControlMask = (1 << EShLangTessControl),
EShLangTessEvaluationMask = (1 << EShLangTessEvaluation),
EShLangGeometryMask = (1 << EShLangGeometry),
EShLangFragmentMask = (1 << EShLangFragment),
EShLangComputeMask = (1 << EShLangCompute),
EShLangRayGenNVMask = (1 << EShLangRayGenNV),
EShLangIntersectNVMask = (1 << EShLangIntersectNV),
EShLangAnyHitNVMask = (1 << EShLangAnyHitNV),
EShLangClosestHitNVMask = (1 << EShLangClosestHitNV),
EShLangMissNVMask = (1 << EShLangMissNV),
EShLangCallableNVMask = (1 << EShLangCallableNV),
EShLangRayGenMask = (1 << EShLangRayGen),
EShLangRayGenNVMask = EShLangRayGenMask,
EShLangIntersectMask = (1 << EShLangIntersect),
EShLangIntersectNVMask = EShLangIntersectMask,
EShLangAnyHitMask = (1 << EShLangAnyHit),
EShLangAnyHitNVMask = EShLangAnyHitMask,
EShLangClosestHitMask = (1 << EShLangClosestHit),
EShLangClosestHitNVMask = EShLangClosestHitMask,
EShLangMissMask = (1 << EShLangMiss),
EShLangMissNVMask = EShLangMissMask,
EShLangCallableMask = (1 << EShLangCallable),
EShLangCallableNVMask = EShLangCallableMask,
EShLangTaskNVMask = (1 << EShLangTaskNV),
EShLangMeshNVMask = (1 << EShLangMeshNV),
LAST_ELEMENT_MARKER(EShLanguageMaskCount),
} EShLanguageMask;
namespace glslang {
@ -128,24 +145,30 @@ typedef enum {
EShSourceNone,
EShSourceGlsl, // GLSL, includes ESSL (OpenGL ES GLSL)
EShSourceHlsl, // HLSL
LAST_ELEMENT_MARKER(EShSourceCount),
} EShSource; // if EShLanguage were EShStage, this could be EShLanguage instead
typedef enum {
EShClientNone, // use when there is no client, e.g. for validation
EShClientVulkan,
EShClientOpenGL,
EShClientVulkan, // as GLSL dialect, specifies KHR_vulkan_glsl extension
EShClientOpenGL, // as GLSL dialect, specifies ARB_gl_spirv extension
LAST_ELEMENT_MARKER(EShClientCount),
} EShClient;
typedef enum {
EShTargetNone,
EShTargetSpv, // SPIR-V (preferred spelling)
EshTargetSpv = EShTargetSpv, // legacy spelling
LAST_ELEMENT_MARKER(EShTargetCount),
} EShTargetLanguage;
typedef enum {
EShTargetVulkan_1_0 = (1 << 22), // Vulkan 1.0
EShTargetVulkan_1_1 = (1 << 22) | (1 << 12), // Vulkan 1.1
EShTargetVulkan_1_2 = (1 << 22) | (2 << 12), // Vulkan 1.2
EShTargetVulkan_1_3 = (1 << 22) | (3 << 12), // Vulkan 1.3
EShTargetOpenGL_450 = 450, // OpenGL
LAST_ELEMENT_MARKER(EShTargetClientVersionCount = 5),
} EShTargetClientVersion;
typedef EShTargetClientVersion EshTargetClientVersion;
@ -157,6 +180,8 @@ typedef enum {
EShTargetSpv_1_3 = (1 << 16) | (3 << 8), // SPIR-V 1.3
EShTargetSpv_1_4 = (1 << 16) | (4 << 8), // SPIR-V 1.4
EShTargetSpv_1_5 = (1 << 16) | (5 << 8), // SPIR-V 1.5
EShTargetSpv_1_6 = (1 << 16) | (6 << 8), // SPIR-V 1.6
LAST_ELEMENT_MARKER(EShTargetLanguageVersionCount = 7),
} EShTargetLanguageVersion;
struct TInputLanguage {
@ -164,6 +189,7 @@ struct TInputLanguage {
EShLanguage stage; // redundant information with other input, this one overrides when not EShSourceNone
EShClient dialect;
int dialectVersion; // version of client's language definition, not the client (when not EShClientNone)
bool vulkanRulesRelaxed;
};
struct TClient {
@ -186,7 +212,7 @@ struct TEnvironment {
TTarget target; // what to generate
};
const char* StageName(EShLanguage);
GLSLANG_EXPORT const char* StageName(EShLanguage);
} // end namespace glslang
@ -206,6 +232,7 @@ typedef enum {
EShOptNone,
EShOptSimple, // Optimizations that can be done quickly
EShOptFull, // Optimizations that will take more time
LAST_ELEMENT_MARKER(EshOptLevelCount),
} EShOptimizationLevel;
//
@ -214,12 +241,13 @@ typedef enum {
typedef enum {
EShTexSampTransKeep, // keep textures and samplers as is (default)
EShTexSampTransUpgradeTextureRemoveSampler, // change texture w/o embeded sampler into sampled texture and throw away all samplers
LAST_ELEMENT_MARKER(EShTexSampTransCount),
} EShTextureSamplerTransformMode;
//
// Message choices for what errors and warnings are given.
//
enum EShMessages {
enum EShMessages : unsigned {
EShMsgDefault = 0, // default is to give all required errors and extra warnings
EShMsgRelaxedErrors = (1 << 0), // be liberal in accepting input
EShMsgSuppressWarnings = (1 << 1), // suppress all warnings, except those required by the specification
@ -234,21 +262,27 @@ enum EShMessages {
EShMsgDebugInfo = (1 << 10), // save debug information
EShMsgHlslEnable16BitTypes = (1 << 11), // enable use of 16-bit types in SPIR-V for HLSL
EShMsgHlslLegalization = (1 << 12), // enable HLSL Legalization messages
EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (right now only for samplers)
EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (for samplers and semantics)
EShMsgBuiltinSymbolTable = (1 << 14), // print the builtin symbol table
EShMsgEnhanced = (1 << 15), // enhanced message readability
LAST_ELEMENT_MARKER(EShMsgCount),
};
//
// Options for building reflection
//
typedef enum {
EShReflectionDefault = 0, // default is original behaviour before options were added
EShReflectionStrictArraySuffix = (1 << 0), // reflection will follow stricter rules for array-of-structs suffixes
EShReflectionBasicArraySuffix = (1 << 1), // arrays of basic types will be appended with [0] as in GL reflection
EShReflectionIntermediateIO = (1 << 2), // reflect inputs and outputs to program, even with no vertex shader
EShReflectionSeparateBuffers = (1 << 3), // buffer variables and buffer blocks are reflected separately
EShReflectionAllBlockVariables = (1 << 4), // reflect all variables in blocks, even if they are inactive
EShReflectionUnwrapIOBlocks = (1 << 5), // unwrap input/output blocks the same as with uniform blocks
EShReflectionDefault = 0, // default is original behaviour before options were added
EShReflectionStrictArraySuffix = (1 << 0), // reflection will follow stricter rules for array-of-structs suffixes
EShReflectionBasicArraySuffix = (1 << 1), // arrays of basic types will be appended with [0] as in GL reflection
EShReflectionIntermediateIO = (1 << 2), // reflect inputs and outputs to program, even with no vertex shader
EShReflectionSeparateBuffers = (1 << 3), // buffer variables and buffer blocks are reflected separately
EShReflectionAllBlockVariables = (1 << 4), // reflect all variables in blocks, even if they are inactive
EShReflectionUnwrapIOBlocks = (1 << 5), // unwrap input/output blocks the same as with uniform blocks
EShReflectionAllIOVariables = (1 << 6), // reflect all input/output variables, even if they are inactive
EShReflectionSharedStd140SSBO = (1 << 7), // Apply std140/shared rules for ubo to ssbo
EShReflectionSharedStd140UBO = (1 << 8), // Apply std140/shared rules for ubo to ssbo
LAST_ELEMENT_MARKER(EShReflectionCount),
} EShReflectionOptions;
//
@ -280,10 +314,10 @@ typedef void* ShHandle;
// Driver calls these to create and destroy compiler/linker
// objects.
//
SH_IMPORT_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int debugOptions); // one per shader
SH_IMPORT_EXPORT ShHandle ShConstructLinker(const EShExecutable, int debugOptions); // one per shader pair
SH_IMPORT_EXPORT ShHandle ShConstructUniformMap(); // one per uniform namespace (currently entire program object)
SH_IMPORT_EXPORT void ShDestruct(ShHandle);
GLSLANG_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int debugOptions); // one per shader
GLSLANG_EXPORT ShHandle ShConstructLinker(const EShExecutable, int debugOptions); // one per shader pair
GLSLANG_EXPORT ShHandle ShConstructUniformMap(); // one per uniform namespace (currently entire program object)
GLSLANG_EXPORT void ShDestruct(ShHandle);
//
// The return value of ShCompile is boolean, non-zero indicating
@ -292,7 +326,7 @@ SH_IMPORT_EXPORT void ShDestruct(ShHandle);
// The info-log should be written by ShCompile into
// ShHandle, so it can answer future queries.
//
SH_IMPORT_EXPORT int ShCompile(
GLSLANG_EXPORT int ShCompile(
const ShHandle,
const char* const shaderStrings[],
const int numStrings,
@ -305,7 +339,7 @@ SH_IMPORT_EXPORT int ShCompile(
EShMessages messages = EShMsgDefault // warnings and errors
);
SH_IMPORT_EXPORT int ShLinkExt(
GLSLANG_EXPORT int ShLinkExt(
const ShHandle, // linker object
const ShHandle h[], // compiler objects to link together
const int numHandles);
@ -314,26 +348,26 @@ SH_IMPORT_EXPORT int ShLinkExt(
// ShSetEncrpytionMethod is a place-holder for specifying
// how source code is encrypted.
//
SH_IMPORT_EXPORT void ShSetEncryptionMethod(ShHandle);
GLSLANG_EXPORT void ShSetEncryptionMethod(ShHandle);
//
// All the following return 0 if the information is not
// available in the object passed down, or the object is bad.
//
SH_IMPORT_EXPORT const char* ShGetInfoLog(const ShHandle);
SH_IMPORT_EXPORT const void* ShGetExecutable(const ShHandle);
SH_IMPORT_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*); // to detect user aliasing
SH_IMPORT_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*); // to force any physical mappings
GLSLANG_EXPORT const char* ShGetInfoLog(const ShHandle);
GLSLANG_EXPORT const void* ShGetExecutable(const ShHandle);
GLSLANG_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*); // to detect user aliasing
GLSLANG_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*); // to force any physical mappings
//
// Tell the linker to never assign a vertex attribute to this list of physical attributes
//
SH_IMPORT_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count);
GLSLANG_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count);
//
// Returns the location ID of the named uniform.
// Returns -1 if error.
//
SH_IMPORT_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name);
GLSLANG_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name);
#ifdef __cplusplus
} // end extern "C"
@ -364,19 +398,27 @@ class TInfoSink;
namespace glslang {
const char* GetEsslVersionString();
const char* GetGlslVersionString();
int GetKhronosToolId();
struct Version {
int major;
int minor;
int patch;
const char* flavor;
};
GLSLANG_EXPORT Version GetVersion();
GLSLANG_EXPORT const char* GetEsslVersionString();
GLSLANG_EXPORT const char* GetGlslVersionString();
GLSLANG_EXPORT int GetKhronosToolId();
class TIntermediate;
class TProgram;
class TPoolAllocator;
// Call this exactly once per process before using anything else
bool InitializeProcess();
GLSLANG_EXPORT bool InitializeProcess();
// Call once per process to tear down everything
void FinalizeProcess();
GLSLANG_EXPORT void FinalizeProcess();
// Resource type for IO resolver
enum TResourceType {
@ -389,11 +431,22 @@ enum TResourceType {
EResCount
};
enum TBlockStorageClass
{
EbsUniform = 0,
EbsStorageBuffer,
EbsPushConstant,
EbsNone, // not a uniform or buffer variable
EbsCount,
};
// Make one TShader per shader that you will link into a program. Then
// - provide the shader through setStrings() or setStringsWithLengths()
// - optionally call setEnv*(), see below for more detail
// - optionally use setPreamble() to set a special shader string that will be
// processed before all others but won't affect the validity of #version
// - optionally call addProcesses() for each setting/transform,
// see comment for class TProcesses
// - call parse(): source language and target environment must be selected
// either by correct setting of EShMessages sent to parse(), or by
// explicitly calling setEnv*()
@ -406,40 +459,53 @@ enum TResourceType {
//
class TShader {
public:
explicit TShader(EShLanguage);
virtual ~TShader();
void setStrings(const char* const* s, int n);
void setStringsWithLengths(const char* const* s, const int* l, int n);
void setStringsWithLengthsAndNames(
GLSLANG_EXPORT explicit TShader(EShLanguage);
GLSLANG_EXPORT virtual ~TShader();
GLSLANG_EXPORT void setStrings(const char* const* s, int n);
GLSLANG_EXPORT void setStringsWithLengths(
const char* const* s, const int* l, int n);
GLSLANG_EXPORT void setStringsWithLengthsAndNames(
const char* const* s, const int* l, const char* const* names, int n);
void setPreamble(const char* s) { preamble = s; }
void setEntryPoint(const char* entryPoint);
void setSourceEntryPoint(const char* sourceEntryPointName);
void addProcesses(const std::vector<std::string>&);
GLSLANG_EXPORT void setEntryPoint(const char* entryPoint);
GLSLANG_EXPORT void setSourceEntryPoint(const char* sourceEntryPointName);
GLSLANG_EXPORT void addProcesses(const std::vector<std::string>&);
GLSLANG_EXPORT void setUniqueId(unsigned long long id);
GLSLANG_EXPORT void setOverrideVersion(int version);
// IO resolver binding data: see comments in ShaderLang.cpp
void setShiftBinding(TResourceType res, unsigned int base);
void setShiftSamplerBinding(unsigned int base); // DEPRECATED: use setShiftBinding
void setShiftTextureBinding(unsigned int base); // DEPRECATED: use setShiftBinding
void setShiftImageBinding(unsigned int base); // DEPRECATED: use setShiftBinding
void setShiftUboBinding(unsigned int base); // DEPRECATED: use setShiftBinding
void setShiftUavBinding(unsigned int base); // DEPRECATED: use setShiftBinding
void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding
void setShiftSsboBinding(unsigned int base); // DEPRECATED: use setShiftBinding
void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set);
void setResourceSetBinding(const std::vector<std::string>& base);
void setAutoMapBindings(bool map);
void setAutoMapLocations(bool map);
void addUniformLocationOverride(const char* name, int loc);
void setUniformLocationBase(int base);
void setInvertY(bool invert);
GLSLANG_EXPORT void setShiftBinding(TResourceType res, unsigned int base);
GLSLANG_EXPORT void setShiftSamplerBinding(unsigned int base); // DEPRECATED: use setShiftBinding
GLSLANG_EXPORT void setShiftTextureBinding(unsigned int base); // DEPRECATED: use setShiftBinding
GLSLANG_EXPORT void setShiftImageBinding(unsigned int base); // DEPRECATED: use setShiftBinding
GLSLANG_EXPORT void setShiftUboBinding(unsigned int base); // DEPRECATED: use setShiftBinding
GLSLANG_EXPORT void setShiftUavBinding(unsigned int base); // DEPRECATED: use setShiftBinding
GLSLANG_EXPORT void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding
GLSLANG_EXPORT void setShiftSsboBinding(unsigned int base); // DEPRECATED: use setShiftBinding
GLSLANG_EXPORT void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set);
GLSLANG_EXPORT void setResourceSetBinding(const std::vector<std::string>& base);
GLSLANG_EXPORT void setAutoMapBindings(bool map);
GLSLANG_EXPORT void setAutoMapLocations(bool map);
GLSLANG_EXPORT void addUniformLocationOverride(const char* name, int loc);
GLSLANG_EXPORT void setUniformLocationBase(int base);
GLSLANG_EXPORT void setInvertY(bool invert);
GLSLANG_EXPORT void setDxPositionW(bool dxPosW);
GLSLANG_EXPORT void setEnhancedMsgs();
#ifdef ENABLE_HLSL
void setHlslIoMapping(bool hlslIoMap);
void setFlattenUniformArrays(bool flatten);
GLSLANG_EXPORT void setHlslIoMapping(bool hlslIoMap);
GLSLANG_EXPORT void setFlattenUniformArrays(bool flatten);
#endif
void setNoStorageFormat(bool useUnknownFormat);
void setNanMinMaxClamp(bool nanMinMaxClamp);
void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
GLSLANG_EXPORT void setNoStorageFormat(bool useUnknownFormat);
GLSLANG_EXPORT void setNanMinMaxClamp(bool nanMinMaxClamp);
GLSLANG_EXPORT void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
GLSLANG_EXPORT void addBlockStorageOverride(const char* nameStr, glslang::TBlockStorageClass backing);
GLSLANG_EXPORT void setGlobalUniformBlockName(const char* name);
GLSLANG_EXPORT void setAtomicCounterBlockName(const char* name);
GLSLANG_EXPORT void setGlobalUniformSet(unsigned int set);
GLSLANG_EXPORT void setGlobalUniformBinding(unsigned int binding);
GLSLANG_EXPORT void setAtomicCounterBlockSet(unsigned int set);
GLSLANG_EXPORT void setAtomicCounterBlockBinding(unsigned int binding);
// For setting up the environment (cleared to nothingness in the constructor).
// These must be called so that parsing is done for the right source language and
@ -448,10 +514,13 @@ public:
//
// setEnvInput: The input source language and stage. If generating code for a
// specific client, the input client semantics to use and the
// version of the that client's input semantics to use, otherwise
// version of that client's input semantics to use, otherwise
// use EShClientNone and version of 0, e.g. for validation mode.
// Note 'version' does not describe the target environment,
// just the version of the source dialect to compile under.
// For example, to choose the Vulkan dialect of GLSL defined by
// version 100 of the KHR_vulkan_glsl extension: lang = EShSourceGlsl,
// dialect = EShClientVulkan, and version = 100.
//
// See the definitions of TEnvironment, EShSource, EShLanguage,
// and EShClient for choices and more detail.
@ -496,6 +565,9 @@ public:
bool getEnvTargetHlslFunctionality1() const { return false; }
#endif
void setEnvInputVulkanRulesRelaxed() { environment.input.vulkanRulesRelaxed = true; }
bool getEnvInputVulkanRulesRelaxed() const { return environment.input.vulkanRulesRelaxed; }
// Interface to #include handlers.
//
// To support #include, a client of Glslang does the following:
@ -579,8 +651,10 @@ public:
virtual void releaseInclude(IncludeResult*) override { }
};
bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
bool forwardCompatible, EShMessages, Includer&);
GLSLANG_EXPORT bool parse(
const TBuiltInResource*, int defaultVersion, EProfile defaultProfile,
bool forceDefaultVersionAndProfile, bool forwardCompatible,
EShMessages, Includer&);
bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
bool forwardCompatible, EShMessages messages)
@ -603,13 +677,14 @@ public:
// 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,
int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
bool forwardCompatible, EShMessages message, std::string* outputString,
Includer& includer);
GLSLANG_EXPORT bool preprocess(
const TBuiltInResource* builtInResources, int defaultVersion,
EProfile defaultProfile, bool forceDefaultVersionAndProfile,
bool forwardCompatible, EShMessages message, std::string* outputString,
Includer& includer);
const char* getInfoLog();
const char* getInfoDebugLog();
GLSLANG_EXPORT const char* getInfoLog();
GLSLANG_EXPORT const char* getInfoDebugLog();
EShLanguage getStage() const { return stage; }
TIntermediate* getIntermediate() const { return intermediate; }
@ -628,15 +703,18 @@ protected:
// stringNames is the optional names for all the strings. If stringNames
// is null, then none of the strings has name. If a certain element in
// stringNames is null, then the corresponding string does not have name.
const char* const* strings;
const char* const* strings; // explicit code to compile, see previous comment
const int* lengths;
const char* const* stringNames;
const char* preamble;
int numStrings;
int numStrings; // size of the above arrays
const char* preamble; // string of implicit code to compile before the explicitly provided code
// a function in the source string can be renamed FROM this TO the name given in setEntryPoint.
std::string sourceEntryPointName;
// overrides #version in shader source or default version if #version isn't present
int overrideVersion;
TEnvironment environment;
friend class TProgram;
@ -645,7 +723,7 @@ private:
TShader& operator=(TShader&);
};
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
//
// A reflection database and its interface, consistent with the OpenGL API reflection queries.
@ -654,11 +732,11 @@ private:
// Data needed for just a single object at the granularity exchanged by the reflection API
class TObjectReflection {
public:
TObjectReflection(const std::string& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex);
GLSLANG_EXPORT TObjectReflection(const std::string& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex);
const TType* getType() const { return type; }
int getBinding() const;
void dump() const;
GLSLANG_EXPORT int getBinding() const;
GLSLANG_EXPORT void dump() const;
static TObjectReflection badReflection() { return TObjectReflection(); }
std::string name;
@ -669,6 +747,7 @@ public:
int counterIndex;
int numMembers;
int arrayStride; // stride of an array variable
int topLevelArraySize; // size of the top-level variable in a storage buffer member
int topLevelArrayStride; // stride of the top-level variable in a storage buffer member
EShLanguageMask stages;
@ -759,10 +838,10 @@ public:
// Called by TSlotCollector to resolve resource locations or bindings
virtual void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0;
// Called by mapIO.addStage to set shader stage mask to mark a stage be added to this pipeline
virtual void addStage(EShLanguage stage) = 0;
virtual void addStage(EShLanguage stage, TIntermediate& stageIntermediate) = 0;
};
#endif // GLSLANG_WEB
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
// Make one TProgram per set of shaders that will get linked together. Add all
// the shaders that are to be linked together. After calling shader.parse()
@ -772,40 +851,40 @@ public:
//
class TProgram {
public:
TProgram();
virtual ~TProgram();
GLSLANG_EXPORT TProgram();
GLSLANG_EXPORT virtual ~TProgram();
void addShader(TShader* shader) { stages[shader->stage].push_back(shader); }
std::list<TShader*>& getShaders(EShLanguage stage) { return stages[stage]; }
// Link Validation interface
bool link(EShMessages);
const char* getInfoLog();
const char* getInfoDebugLog();
GLSLANG_EXPORT bool link(EShMessages);
GLSLANG_EXPORT const char* getInfoLog();
GLSLANG_EXPORT const char* getInfoDebugLog();
TIntermediate* getIntermediate(EShLanguage stage) const { return intermediate[stage]; }
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
// Reflection Interface
// call first, to do liveness analysis, index mapping, etc.; returns false on failure
bool buildReflection(int opts = EShReflectionDefault);
unsigned getLocalSize(int dim) const; // return dim'th local size
int getReflectionIndex(const char *name) const;
int getReflectionPipeIOIndex(const char* name, const bool inOrOut) const;
int getNumUniformVariables() const;
const TObjectReflection& getUniform(int index) const;
int getNumUniformBlocks() const;
const TObjectReflection& getUniformBlock(int index) const;
int getNumPipeInputs() const;
const TObjectReflection& getPipeInput(int index) const;
int getNumPipeOutputs() const;
const TObjectReflection& getPipeOutput(int index) const;
int getNumBufferVariables() const;
const TObjectReflection& getBufferVariable(int index) const;
int getNumBufferBlocks() const;
const TObjectReflection& getBufferBlock(int index) const;
int getNumAtomicCounters() const;
const TObjectReflection& getAtomicCounter(int index) const;
GLSLANG_EXPORT bool buildReflection(int opts = EShReflectionDefault);
GLSLANG_EXPORT unsigned getLocalSize(int dim) const; // return dim'th local size
GLSLANG_EXPORT int getReflectionIndex(const char *name) const;
GLSLANG_EXPORT int getReflectionPipeIOIndex(const char* name, const bool inOrOut) const;
GLSLANG_EXPORT int getNumUniformVariables() const;
GLSLANG_EXPORT const TObjectReflection& getUniform(int index) const;
GLSLANG_EXPORT int getNumUniformBlocks() const;
GLSLANG_EXPORT const TObjectReflection& getUniformBlock(int index) const;
GLSLANG_EXPORT int getNumPipeInputs() const;
GLSLANG_EXPORT const TObjectReflection& getPipeInput(int index) const;
GLSLANG_EXPORT int getNumPipeOutputs() const;
GLSLANG_EXPORT const TObjectReflection& getPipeOutput(int index) const;
GLSLANG_EXPORT int getNumBufferVariables() const;
GLSLANG_EXPORT const TObjectReflection& getBufferVariable(int index) const;
GLSLANG_EXPORT int getNumBufferBlocks() const;
GLSLANG_EXPORT const TObjectReflection& getBufferBlock(int index) const;
GLSLANG_EXPORT int getNumAtomicCounters() const;
GLSLANG_EXPORT const TObjectReflection& getAtomicCounter(int index) const;
// Legacy Reflection Interface - expressed in terms of above interface
@ -872,22 +951,23 @@ public:
// returns a TType*
const TType *getAttributeTType(int index) const { return getPipeInput(index).getType(); }
void dumpReflection();
GLSLANG_EXPORT void dumpReflection();
// I/O mapping: apply base offsets and map live unbound variables
// If resolver is not provided it uses the previous approach
// and respects auto assignment and offsets.
bool mapIO(TIoMapResolver* pResolver = nullptr, TIoMapper* pIoMapper = nullptr);
#endif
GLSLANG_EXPORT bool mapIO(TIoMapResolver* pResolver = nullptr, TIoMapper* pIoMapper = nullptr);
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
protected:
bool linkStage(EShLanguage, EShMessages);
GLSLANG_EXPORT bool linkStage(EShLanguage, EShMessages);
GLSLANG_EXPORT bool crossStageCheck(EShMessages);
TPoolAllocator* pool;
std::list<TShader*> stages[EShLangCount];
TIntermediate* intermediate[EShLangCount];
bool newedIntermediate[EShLangCount]; // track which intermediate were "new" versus reusing a singleton unit in a stage
TInfoSink* infoSink;
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
TReflection* reflection;
#endif
bool linked;

View file

@ -1,5 +1,38 @@
#!/bin/bash
# Copyright (C) 2020 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 The Khronos Group Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
if [ "$1" = 'web' ]
then
m4 -P -DGLSLANG_WEB MachineIndependent/glslang.m4 > MachineIndependent/glslang.y

View file

@ -35,5 +35,9 @@ static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shade
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";
static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation";
static const char* const E_SPV_EXT_shader_atomic_float_add = "SPV_EXT_shader_atomic_float_add";
static const char* const E_SPV_EXT_shader_atomic_float16_add = "SPV_EXT_shader_atomic_float16_add";
static const char* const E_SPV_EXT_shader_atomic_float_min_max = "SPV_EXT_shader_atomic_float_min_max";
static const char* const E_SPV_EXT_shader_image_int64 = "SPV_EXT_shader_image_int64";
#endif // #ifndef GLSLextEXT_H

View file

@ -1,5 +1,6 @@
/*
** Copyright (c) 2014-2016 The Khronos Group Inc.
** Copyright (c) 2014-2020 The Khronos Group Inc.
** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and/or associated documentation files (the "Materials"),
@ -28,7 +29,7 @@
#define GLSLextKHR_H
static const int GLSLextKHRVersion = 100;
static const int GLSLextKHRRevision = 2;
static const int GLSLextKHRRevision = 3;
static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot";
static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote";
@ -44,5 +45,13 @@ static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physi
static const char* const E_SPV_KHR_physical_storage_buffer = "SPV_KHR_physical_storage_buffer";
static const char* const E_SPV_EXT_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock";
static const char* const E_SPV_KHR_shader_clock = "SPV_KHR_shader_clock";
static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_semantic_info";
static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing";
static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query";
static const char* const E_SPV_KHR_fragment_shading_rate = "SPV_KHR_fragment_shading_rate";
static const char* const E_SPV_KHR_terminate_invocation = "SPV_KHR_terminate_invocation";
static const char* const E_SPV_KHR_workgroup_memory_explicit_layout = "SPV_KHR_workgroup_memory_explicit_layout";
static const char* const E_SPV_KHR_subgroup_uniform_control_flow = "SPV_KHR_subgroup_uniform_control_flow";
static const char* const E_SPV_KHR_fragment_shader_barycentric = "SPV_KHR_fragment_shader_barycentric";
#endif // #ifndef GLSLextKHR_H

View file

@ -69,6 +69,9 @@ 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_ray_tracing_motion_blur
const char* const E_SPV_NV_ray_tracing_motion_blur = "SPV_NV_ray_tracing_motion_blur";
//SPV_NV_shading_rate
const char* const E_SPV_NV_shading_rate = "SPV_NV_shading_rate";

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,50 @@
// Copyright (c) 2020 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 SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_
#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_
#ifdef __cplusplus
extern "C" {
#endif
enum {
NonSemanticDebugPrintfRevision = 1,
NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff
};
enum NonSemanticDebugPrintfInstructions {
NonSemanticDebugPrintfDebugPrintf = 1,
NonSemanticDebugPrintfInstructionsMax = 0x7fffffff
};
#ifdef __cplusplus
}
#endif
#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_

View file

@ -160,15 +160,29 @@ namespace spv {
}
// Is this an opcode we should remove when using --strip?
bool spirvbin_t::isStripOp(spv::Op opCode) const
bool spirvbin_t::isStripOp(spv::Op opCode, unsigned start) const
{
switch (opCode) {
case spv::OpSource:
case spv::OpSourceExtension:
case spv::OpName:
case spv::OpMemberName:
case spv::OpLine: return true;
default: return false;
case spv::OpLine :
{
const std::string name = literalString(start + 2);
std::vector<std::string>::const_iterator it;
for (it = stripWhiteList.begin(); it < stripWhiteList.end(); it++)
{
if (name.find(*it) != std::string::npos) {
return false;
}
}
return true;
}
default :
return false;
}
}
@ -297,15 +311,21 @@ namespace spv {
std::string spirvbin_t::literalString(unsigned word) const
{
std::string literal;
const spirword_t * pos = spv.data() + word;
literal.reserve(16);
const char* bytes = reinterpret_cast<const char*>(spv.data() + word);
while (bytes && *bytes)
literal += *bytes++;
return literal;
do {
spirword_t word = *pos;
for (int i = 0; i < 4; i++) {
char c = word & 0xff;
if (c == '\0')
return literal;
literal += c;
word >>= 8;
}
pos++;
} while (true);
}
void spirvbin_t::applyMap()
@ -366,7 +386,7 @@ namespace spv {
process(
[&](spv::Op opCode, unsigned start) {
// remember opcodes we want to strip later
if (isStripOp(opCode))
if (isStripOp(opCode, start))
stripInst(start);
return true;
},
@ -544,6 +564,9 @@ namespace spv {
// Extended instructions: currently, assume everything is an ID.
// TODO: add whatever data we need for exceptions to that
if (opCode == spv::OpExtInst) {
idFn(asId(word)); // Instruction set is an ID that also needs to be mapped
word += 2; // instruction set, and instruction from set
numOperands -= 2;
@ -625,6 +648,9 @@ namespace spv {
break;
}
case spv::OperandVariableLiteralStrings:
return nextInst;
// Execution mode might have extra literal operands. Skip them.
case spv::OperandExecutionMode:
return nextInst;
@ -827,7 +853,15 @@ namespace spv {
[&](spv::Id& id) {
if (thisOpCode != spv::OpNop) {
++idCounter;
const std::uint32_t hashval = opCounter[thisOpCode] * thisOpCode * 50047 + idCounter + fnId * 117;
const std::uint32_t hashval =
// Explicitly cast operands to unsigned int to avoid integer
// promotion to signed int followed by integer overflow,
// which would result in undefined behavior.
static_cast<unsigned int>(opCounter[thisOpCode])
* thisOpCode
* 50047
+ idCounter
+ static_cast<unsigned int>(fnId) * 117;
if (isOldIdUnmapped(id))
localId(id, nextUnusedId(hashval % softTypeIdLimit + firstMappedID));
@ -1474,13 +1508,24 @@ namespace spv {
}
// remap from a memory image
void spirvbin_t::remap(std::vector<std::uint32_t>& in_spv, std::uint32_t opts)
void spirvbin_t::remap(std::vector<std::uint32_t>& in_spv, const std::vector<std::string>& whiteListStrings,
std::uint32_t opts)
{
stripWhiteList = whiteListStrings;
spv.swap(in_spv);
remap(opts);
spv.swap(in_spv);
}
// remap from a memory image - legacy interface without white list
void spirvbin_t::remap(std::vector<std::uint32_t>& in_spv, std::uint32_t opts)
{
stripWhiteList.clear();
spv.swap(in_spv);
remap(opts);
spv.swap(in_spv);
}
} // namespace SPV
#endif // defined (use_cpp11)

View file

@ -118,6 +118,10 @@ public:
virtual ~spirvbin_t() { }
// remap on an existing binary in memory
void remap(std::vector<std::uint32_t>& spv, const std::vector<std::string>& whiteListStrings,
std::uint32_t opts = DO_EVERYTHING);
// remap on an existing binary in memory - legacy interface without white list
void remap(std::vector<std::uint32_t>& spv, std::uint32_t opts = DO_EVERYTHING);
// Type for error/log handler functions
@ -180,6 +184,8 @@ private:
unsigned typeSizeInWords(spv::Id id) const;
unsigned idTypeSizeInWords(spv::Id id) const;
bool isStripOp(spv::Op opCode, unsigned start) const;
spv::Id& asId(unsigned word) { return spv[word]; }
const spv::Id& asId(unsigned word) const { return spv[word]; }
spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); }
@ -249,6 +255,8 @@ private:
std::vector<spirword_t> spv; // SPIR words
std::vector<std::string> stripWhiteList;
namemap_t nameMap; // ID names from OpName
// Since we want to also do binary ops, we can't use std::vector<bool>. we could use

View file

@ -1,6 +1,7 @@
//
// Copyright (C) 2014-2015 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@ -426,6 +427,37 @@ Id Builder::makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols)
return type->getResultId();
}
Id Builder::makeGenericType(spv::Op opcode, std::vector<spv::IdImmediate>& operands)
{
// try to find it
Instruction* type;
for (int t = 0; t < (int)groupedTypes[opcode].size(); ++t) {
type = groupedTypes[opcode][t];
if (static_cast<size_t>(type->getNumOperands()) != operands.size())
continue; // Number mismatch, find next
bool match = true;
for (int op = 0; match && op < (int)operands.size(); ++op) {
match = (operands[op].isId ? type->getIdOperand(op) : type->getImmediateOperand(op)) == operands[op].word;
}
if (match)
return type->getResultId();
}
// not found, make it
type = new Instruction(getUniqueId(), NoType, opcode);
for (size_t op = 0; op < operands.size(); ++op) {
if (operands[op].isId)
type->addIdOperand(operands[op].word);
else
type->addImmediateOperand(operands[op].word);
}
groupedTypes[opcode].push_back(type);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
return type->getResultId();
}
// TODO: performance: track arrays per stride
// If a stride is supplied (non-zero) make an array.
@ -496,7 +528,8 @@ Id Builder::makeFunctionType(Id returnType, const std::vector<Id>& paramTypes)
return type->getResultId();
}
Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format)
Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled,
ImageFormat format)
{
assert(sampled == 1 || sampled == 2);
@ -601,16 +634,31 @@ Id Builder::makeSampledImageType(Id imageType)
}
#ifndef GLSLANG_WEB
Id Builder::makeAccelerationStructureNVType()
Id Builder::makeAccelerationStructureType()
{
Instruction *type;
if (groupedTypes[OpTypeAccelerationStructureNV].size() == 0) {
type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureNV);
groupedTypes[OpTypeAccelerationStructureNV].push_back(type);
if (groupedTypes[OpTypeAccelerationStructureKHR].size() == 0) {
type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureKHR);
groupedTypes[OpTypeAccelerationStructureKHR].push_back(type);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
} else {
type = groupedTypes[OpTypeAccelerationStructureNV].back();
type = groupedTypes[OpTypeAccelerationStructureKHR].back();
}
return type->getResultId();
}
Id Builder::makeRayQueryType()
{
Instruction *type;
if (groupedTypes[OpTypeRayQueryKHR].size() == 0) {
type = new Instruction(getUniqueId(), NoType, OpTypeRayQueryKHR);
groupedTypes[OpTypeRayQueryKHR].push_back(type);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
} else {
type = groupedTypes[OpTypeRayQueryKHR].back();
}
return type->getResultId();
@ -726,6 +774,26 @@ Id Builder::getContainedTypeId(Id typeId, int member) const
}
}
// Figure out the final resulting type of the access chain.
Id Builder::getResultingAccessChainType() const
{
assert(accessChain.base != NoResult);
Id typeId = getTypeId(accessChain.base);
assert(isPointerType(typeId));
typeId = getContainedTypeId(typeId);
for (int i = 0; i < (int)accessChain.indexChain.size(); ++i) {
if (isStructType(typeId)) {
assert(isConstantScalar(accessChain.indexChain[i]));
typeId = getContainedTypeId(typeId, getConstantScalar(accessChain.indexChain[i]));
} else
typeId = getContainedTypeId(typeId, accessChain.indexChain[i]);
}
return typeId;
}
// Return the immediately contained type of a given composite type.
Id Builder::getContainedTypeId(Id typeId) const
{
@ -852,6 +920,30 @@ bool Builder::isSpecConstantOpCode(Op opcode) const
}
}
Id Builder::makeNullConstant(Id typeId)
{
Instruction* constant;
// See if we already made it.
Id existing = NoResult;
for (int i = 0; i < (int)nullConstants.size(); ++i) {
constant = nullConstants[i];
if (constant->getTypeId() == typeId)
existing = constant->getResultId();
}
if (existing != NoResult)
return existing;
// Make it
Instruction* c = new Instruction(getUniqueId(), typeId, OpConstantNull);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
nullConstants.push_back(c);
module.mapInstruction(c);
return c->getResultId();
}
Id Builder::makeBoolConstant(bool b, bool specConstant)
{
Id typeId = makeBoolType();
@ -1166,6 +1258,28 @@ void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int val
executionModes.push_back(std::unique_ptr<Instruction>(instr));
}
void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, const std::vector<unsigned>& literals)
{
Instruction* instr = new Instruction(OpExecutionMode);
instr->addIdOperand(entryPoint->getId());
instr->addImmediateOperand(mode);
for (auto literal : literals)
instr->addImmediateOperand(literal);
executionModes.push_back(std::unique_ptr<Instruction>(instr));
}
void Builder::addExecutionModeId(Function* entryPoint, ExecutionMode mode, const std::vector<Id>& operandIds)
{
Instruction* instr = new Instruction(OpExecutionModeId);
instr->addIdOperand(entryPoint->getId());
instr->addImmediateOperand(mode);
for (auto operandId : operandIds)
instr->addIdOperand(operandId);
executionModes.push_back(std::unique_ptr<Instruction>(instr));
}
void Builder::addName(Id id, const char* string)
{
Instruction* name = new Instruction(OpName);
@ -1204,7 +1318,7 @@ void Builder::addDecoration(Id id, Decoration decoration, const char* s)
if (decoration == spv::DecorationMax)
return;
Instruction* dec = new Instruction(OpDecorateStringGOOGLE);
Instruction* dec = new Instruction(OpDecorateString);
dec->addIdOperand(id);
dec->addImmediateOperand(decoration);
dec->addStringOperand(s);
@ -1212,6 +1326,34 @@ void Builder::addDecoration(Id id, Decoration decoration, const char* s)
decorations.push_back(std::unique_ptr<Instruction>(dec));
}
void Builder::addDecoration(Id id, Decoration decoration, const std::vector<unsigned>& literals)
{
if (decoration == spv::DecorationMax)
return;
Instruction* dec = new Instruction(OpDecorate);
dec->addIdOperand(id);
dec->addImmediateOperand(decoration);
for (auto literal : literals)
dec->addImmediateOperand(literal);
decorations.push_back(std::unique_ptr<Instruction>(dec));
}
void Builder::addDecoration(Id id, Decoration decoration, const std::vector<const char*>& strings)
{
if (decoration == spv::DecorationMax)
return;
Instruction* dec = new Instruction(OpDecorateString);
dec->addIdOperand(id);
dec->addImmediateOperand(decoration);
for (auto string : strings)
dec->addStringOperand(string);
decorations.push_back(std::unique_ptr<Instruction>(dec));
}
void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration)
{
if (decoration == spv::DecorationMax)
@ -1225,6 +1367,21 @@ void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration)
decorations.push_back(std::unique_ptr<Instruction>(dec));
}
void Builder::addDecorationId(Id id, Decoration decoration, const std::vector<Id>& operandIds)
{
if(decoration == spv::DecorationMax)
return;
Instruction* dec = new Instruction(OpDecorateId);
dec->addIdOperand(id);
dec->addImmediateOperand(decoration);
for (auto operandId : operandIds)
dec->addIdOperand(operandId);
decorations.push_back(std::unique_ptr<Instruction>(dec));
}
void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num)
{
if (decoration == spv::DecorationMax)
@ -1254,6 +1411,36 @@ void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decorat
decorations.push_back(std::unique_ptr<Instruction>(dec));
}
void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector<unsigned>& literals)
{
if (decoration == spv::DecorationMax)
return;
Instruction* dec = new Instruction(OpMemberDecorate);
dec->addIdOperand(id);
dec->addImmediateOperand(member);
dec->addImmediateOperand(decoration);
for (auto literal : literals)
dec->addImmediateOperand(literal);
decorations.push_back(std::unique_ptr<Instruction>(dec));
}
void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector<const char*>& strings)
{
if (decoration == spv::DecorationMax)
return;
Instruction* dec = new Instruction(OpMemberDecorateString);
dec->addIdOperand(id);
dec->addImmediateOperand(member);
dec->addImmediateOperand(decoration);
for (auto string : strings)
dec->addStringOperand(string);
decorations.push_back(std::unique_ptr<Instruction>(dec));
}
// Comments in header
Function* Builder::makeEntryPoint(const char* entryPoint)
{
@ -1270,7 +1457,8 @@ Function* Builder::makeEntryPoint(const char* entryPoint)
// Comments in header
Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name,
const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& decorations, Block **entry)
const std::vector<Id>& paramTypes,
const std::vector<std::vector<Decoration>>& decorations, Block **entry)
{
// Make the function and initial instructions in it
Id typeId = makeFunctionType(returnType, paramTypes);
@ -1279,9 +1467,12 @@ Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const
// Set up the precisions
setPrecision(function->getId(), precision);
function->setReturnPrecision(precision);
for (unsigned p = 0; p < (unsigned)decorations.size(); ++p) {
for (int d = 0; d < (int)decorations[p].size(); ++d)
for (int d = 0; d < (int)decorations[p].size(); ++d) {
addDecoration(firstParamId + p, decorations[p][d]);
function->addParamPrecision(p, decorations[p][d]);
}
}
// CFG
@ -1331,14 +1522,14 @@ void Builder::leaveFunction()
}
// Comments in header
void Builder::makeDiscard()
void Builder::makeStatementTerminator(spv::Op opcode, const char *name)
{
buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(OpKill)));
createAndSetNoPredecessorBlock("post-discard");
buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(opcode)));
createAndSetNoPredecessorBlock(name);
}
// Comments in header
Id Builder::createVariable(StorageClass storageClass, Id type, const char* name, Id initializer)
Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name, Id initializer)
{
Id pointerType = makePointer(storageClass, type);
Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable);
@ -1360,6 +1551,7 @@ Id Builder::createVariable(StorageClass storageClass, Id type, const char* name,
if (name)
addName(inst->getResultId(), name);
setPrecision(inst->getResultId(), precision);
return inst->getResultId();
}
@ -1373,7 +1565,8 @@ Id Builder::createUndefined(Id type)
}
// av/vis/nonprivate are unnecessary and illegal for some storage classes.
spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const
spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc)
const
{
switch (sc) {
case spv::StorageClassUniform:
@ -1392,7 +1585,8 @@ spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAc
}
// Comments in header
void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope,
unsigned int alignment)
{
Instruction* store = new Instruction(OpStore);
store->addIdOperand(lValue);
@ -1414,7 +1608,8 @@ void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAcce
}
// Comments in header
Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
Id Builder::createLoad(Id lValue, spv::Decoration precision, spv::MemoryAccessMask memoryAccess,
spv::Scope scope, unsigned int alignment)
{
Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad);
load->addIdOperand(lValue);
@ -1432,6 +1627,7 @@ Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope
}
buildPoint->addInstruction(std::unique_ptr<Instruction>(load));
setPrecision(load->getResultId(), precision);
return load->getResultId();
}
@ -1440,16 +1636,7 @@ Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope
Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vector<Id>& offsets)
{
// Figure out the final resulting type.
spv::Id typeId = getTypeId(base);
assert(isPointerType(typeId) && offsets.size() > 0);
typeId = getContainedTypeId(typeId);
for (int i = 0; i < (int)offsets.size(); ++i) {
if (isStructType(typeId)) {
assert(isConstantScalar(offsets[i]));
typeId = getContainedTypeId(typeId, getConstantScalar(offsets[i]));
} else
typeId = getContainedTypeId(typeId, offsets[i]);
}
Id typeId = getResultingAccessChainType();
typeId = makePointer(storageClass, typeId);
// Make the instruction
@ -1495,7 +1682,8 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index)
// Generate code for spec constants if in spec constant operation
// generation mode.
if (generatingOpCodeForSpecConst) {
return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite), std::vector<Id>(1, index));
return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite),
std::vector<Id>(1, index));
}
Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
extract->addIdOperand(composite);
@ -1697,7 +1885,8 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector<IdImmediate>& opera
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);
op->addImmediateOperand((unsigned) opCode);
@ -2144,7 +2333,7 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
Op op;
switch (getMostBasicTypeClass(valueType)) {
case OpTypeFloat:
op = equal ? OpFOrdEqual : OpFOrdNotEqual;
op = equal ? OpFOrdEqual : OpFUnordNotEqual;
break;
case OpTypeInt:
default:
@ -2187,7 +2376,8 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
if (constituent == 0)
resultId = subResultId;
else
resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId), precision);
resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId),
precision);
}
return resultId;
@ -2196,7 +2386,8 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
// OpCompositeConstruct
Id Builder::createCompositeConstruct(Id typeId, const std::vector<Id>& constituents)
{
assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size()));
assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 &&
getNumTypeConstituents(typeId) == (int)constituents.size()));
if (generatingOpCodeForSpecConst) {
// Sometime, even in spec-constant-op mode, the constant composite to be
@ -2394,7 +2585,7 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
int row = 0;
int col = 0;
for (int arg = 0; arg < (int)sources.size(); ++arg) {
for (int arg = 0; arg < (int)sources.size() && col < numCols; ++arg) {
Id argComp = sources[arg];
for (int comp = 0; comp < getNumComponents(sources[arg]); ++comp) {
if (getNumComponents(sources[arg]) > 1) {
@ -2406,6 +2597,10 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
row = 0;
col++;
}
if (col == numCols) {
// If more components are provided than fit the matrix, discard the rest.
break;
}
}
}
}
@ -2609,7 +2804,8 @@ void Builder::clearAccessChain()
}
// Comments in header
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType,
AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
{
accessChain.coherentFlags |= coherentFlags;
accessChain.alignment |= alignment;
@ -2635,35 +2831,70 @@ void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizz
}
// Comments in header
void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
void Builder::accessChainStore(Id rvalue, Decoration nonUniform, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
{
assert(accessChain.isRValue == false);
transferAccessChainSwizzle(true);
Id base = collapseAccessChain();
Id source = rvalue;
// dynamic component should be gone
assert(accessChain.component == NoResult);
// If a swizzle exists and is not full and is not dynamic, then the swizzle will be broken into individual stores.
if (accessChain.swizzle.size() > 0 &&
getNumTypeComponents(getResultingAccessChainType()) != (int)accessChain.swizzle.size() &&
accessChain.component == NoResult) {
for (unsigned int i = 0; i < accessChain.swizzle.size(); ++i) {
accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle[i]));
accessChain.instr = NoResult;
// If swizzle still exists, it is out-of-order or not full, we must load the target vector,
// extract and insert elements to perform writeMask and/or swizzle.
if (accessChain.swizzle.size() > 0) {
Id tempBaseId = createLoad(base);
source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle);
Id base = collapseAccessChain();
addDecoration(base, nonUniform);
accessChain.indexChain.pop_back();
accessChain.instr = NoResult;
// dynamic component should be gone
assert(accessChain.component == NoResult);
Id source = createCompositeExtract(rvalue, getContainedTypeId(getTypeId(rvalue)), i);
// 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);
}
}
else {
Id base = collapseAccessChain();
addDecoration(base, nonUniform);
// take LSB of alignment
alignment = alignment & ~(alignment & (alignment-1));
if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) {
memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
Id source = rvalue;
// dynamic component should be gone
assert(accessChain.component == NoResult);
// If swizzle still exists, it may be out-of-order, we must load the target vector,
// extract and insert elements to perform writeMask and/or swizzle.
if (accessChain.swizzle.size() > 0) {
Id tempBaseId = createLoad(base, spv::NoPrecision);
source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle);
}
// 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);
}
createStore(source, base, memoryAccess, scope, alignment);
}
// Comments in header
Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
Id Builder::accessChainLoad(Decoration precision, Decoration l_nonUniform,
Decoration r_nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess,
spv::Scope scope, unsigned int alignment)
{
Id id;
@ -2687,17 +2918,19 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
if (constant) {
id = createCompositeExtract(accessChain.base, swizzleBase, indexes);
setPrecision(id, precision);
} else {
Id lValue = NoResult;
if (spvVersion >= Spv_1_4) {
if (spvVersion >= Spv_1_4 && isValidInitializer(accessChain.base)) {
// make a new function variable for this r-value, using an initializer,
// and mark it as NonWritable so that downstream it can be detected as a lookup
// table
lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable",
accessChain.base);
lValue = createVariable(NoPrecision, StorageClassFunction, getTypeId(accessChain.base),
"indexable", accessChain.base);
addDecoration(lValue, DecorationNonWritable);
} else {
lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable");
lValue = createVariable(NoPrecision, StorageClassFunction, getTypeId(accessChain.base),
"indexable");
// store into it
createStore(accessChain.base, lValue);
}
@ -2706,9 +2939,8 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
accessChain.isRValue = false;
// load through the access chain
id = createLoad(collapseAccessChain());
id = createLoad(collapseAccessChain(), precision);
}
setPrecision(id, precision);
} else
id = accessChain.base; // no precision, it was set when this was defined
} else {
@ -2721,9 +2953,14 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
}
// load through the access chain
id = createLoad(collapseAccessChain(), memoryAccess, scope, alignment);
setPrecision(id, precision);
addDecoration(id, nonUniform);
id = collapseAccessChain();
// Apply nonuniform both to the access chain and the loaded value.
// Buffer accesses need the access chain decorated, and this is where
// loaded image types get decorated. TODO: This should maybe move to
// createImageTextureFunctionCall.
addDecoration(id, l_nonUniform);
id = createLoad(id, precision, memoryAccess, scope, alignment);
addDecoration(id, r_nonUniform);
}
// Done, unless there are swizzles to do
@ -2744,7 +2981,7 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
if (accessChain.component != NoResult)
id = setPrecision(createVectorExtractDynamic(id, resultType, accessChain.component), precision);
addDecoration(id, nonUniform);
addDecoration(id, r_nonUniform);
return id;
}
@ -3075,7 +3312,8 @@ void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
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) {
instructions[i]->dump(out);

View file

@ -1,7 +1,8 @@
//
// Copyright (C) 2014-2015 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2015-2020 Google, Inc.
// Copyright (C) 2017 ARM Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@ -94,9 +95,14 @@ public:
const char* file_c_str = str.c_str();
fileString->addStringOperand(file_c_str);
strings.push_back(std::unique_ptr<Instruction>(fileString));
module.mapInstruction(fileString);
stringIds[file_c_str] = strId;
return strId;
}
spv::Id getSourceFile() const
{
return sourceFileStringId;
}
void setSourceFile(const std::string& file)
{
sourceFileStringId = getStringId(file);
@ -179,9 +185,12 @@ public:
Id makeSamplerType();
Id makeSampledImageType(Id imageType);
Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols);
Id makeGenericType(spv::Op opcode, std::vector<spv::IdImmediate>& operands);
// accelerationStructureNV type
Id makeAccelerationStructureNVType();
Id makeAccelerationStructureType();
// rayQueryEXT type
Id makeRayQueryType();
// For querying about types.
Id getTypeId(Id resultId) const { return module.getTypeId(resultId); }
@ -196,7 +205,9 @@ public:
Id getContainedTypeId(Id typeId) const;
Id getContainedTypeId(Id typeId, int) const;
StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); }
ImageFormat getImageTypeFormat(Id typeId) const { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); }
ImageFormat getImageTypeFormat(Id typeId) const
{ return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); }
Id getResultingAccessChainType() const;
bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); }
bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); }
@ -206,12 +217,17 @@ public:
bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); }
bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); }
bool isBoolType(Id typeId) { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
bool isIntType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; }
bool isUintType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; }
bool isBoolType(Id typeId)
{ return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
bool isIntType(Id typeId) const
{ return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; }
bool isUintType(Id typeId) const
{ return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; }
bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; }
bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; }
bool isScalarType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || getTypeClass(typeId) == OpTypeBool; }
bool isScalarType(Id typeId) const
{ return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt ||
getTypeClass(typeId) == OpTypeBool; }
bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; }
bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; }
bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; }
@ -221,7 +237,8 @@ public:
#else
bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; }
#endif
bool isAggregateType(Id typeId) const { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); }
bool isAggregateType(Id typeId) const
{ return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); }
bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; }
bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; }
bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; }
@ -233,9 +250,17 @@ public:
bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); }
bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; }
bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); }
unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); }
unsigned int getConstantScalar(Id resultId) const
{ return module.getInstruction(resultId)->getImmediateOperand(0); }
StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); }
bool isVariableOpCode(Op opcode) const { return opcode == OpVariable; }
bool isVariable(Id resultId) const { return isVariableOpCode(getOpCode(resultId)); }
bool isGlobalStorage(Id resultId) const { return getStorageClass(resultId) != StorageClassFunction; }
bool isGlobalVariable(Id resultId) const { return isVariable(resultId) && isGlobalStorage(resultId); }
// See if a resultId is valid for use as an initializer.
bool isValidInitializer(Id resultId) const { return isConstant(resultId) || isGlobalVariable(resultId); }
int getScalarTypeWidth(Id typeId) const
{
Id scalarTypeId = getScalarTypeId(typeId);
@ -274,15 +299,24 @@ public:
}
// For making new constants (will return old constant if the requested one was already made).
Id makeNullConstant(Id typeId);
Id makeBoolConstant(bool b, bool specConstant = false);
Id makeInt8Constant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); }
Id makeUint8Constant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(8), u, specConstant); }
Id makeInt16Constant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); }
Id makeUint16Constant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(16), u, specConstant); }
Id makeIntConstant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); }
Id makeUintConstant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(32), u, specConstant); }
Id makeInt64Constant(long long i, bool specConstant = false) { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); }
Id makeUint64Constant(unsigned long long u, bool specConstant = false) { return makeInt64Constant(makeUintType(64), u, specConstant); }
Id makeInt8Constant(int i, bool specConstant = false)
{ return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); }
Id makeUint8Constant(unsigned u, bool specConstant = false)
{ return makeIntConstant(makeUintType(8), u, specConstant); }
Id makeInt16Constant(int i, bool specConstant = false)
{ return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); }
Id makeUint16Constant(unsigned u, bool specConstant = false)
{ return makeIntConstant(makeUintType(16), u, specConstant); }
Id makeIntConstant(int i, bool specConstant = false)
{ return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); }
Id makeUintConstant(unsigned u, bool specConstant = false)
{ return makeIntConstant(makeUintType(32), u, specConstant); }
Id makeInt64Constant(long long i, bool specConstant = false)
{ return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); }
Id makeUint64Constant(unsigned long long u, bool specConstant = false)
{ return makeInt64Constant(makeUintType(64), u, specConstant); }
Id makeFloatConstant(float f, bool specConstant = false);
Id makeDoubleConstant(double d, bool specConstant = false);
Id makeFloat16Constant(float f16, bool specConstant = false);
@ -294,13 +328,20 @@ public:
// Methods for adding information outside the CFG.
Instruction* addEntryPoint(ExecutionModel, Function*, const char* name);
void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1);
void addExecutionMode(Function*, ExecutionMode mode, const std::vector<unsigned>& literals);
void addExecutionModeId(Function*, ExecutionMode mode, const std::vector<Id>& operandIds);
void addName(Id, const char* name);
void addMemberName(Id, int member, const char* name);
void addDecoration(Id, Decoration, int num = -1);
void addDecoration(Id, Decoration, const char*);
void addDecoration(Id, Decoration, const std::vector<unsigned>& literals);
void addDecoration(Id, Decoration, const std::vector<const char*>& strings);
void addDecorationId(Id id, Decoration, Id idDecoration);
void addDecorationId(Id id, Decoration, const std::vector<Id>& operandIds);
void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1);
void addMemberDecoration(Id, unsigned int member, Decoration, const char*);
void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector<unsigned>& literals);
void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector<const char*>& strings);
// At the end of what block do the next create*() instructions go?
void setBuildPoint(Block* bp) { buildPoint = bp; }
@ -313,8 +354,8 @@ public:
// Make a shader-style function, and create its entry block if entry is non-zero.
// Return the function, pass back the entry.
// The returned pointer is only valid for the lifetime of this builder.
Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, const std::vector<Id>& paramTypes,
const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name,
const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
// Create a return. An 'implicit' return is one not appearing in the source
// code. In the case of an implicit return, no post-return block is inserted.
@ -323,20 +364,25 @@ public:
// Generate all the code needed to finish up a function.
void leaveFunction();
// Create a discard.
void makeDiscard();
// Create block terminator instruction for certain statements like
// discard, terminate-invocation, terminateRayEXT, or ignoreIntersectionEXT
void makeStatementTerminator(spv::Op opcode, const char *name);
// Create a global or function local or IO variable.
Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult);
Id createVariable(Decoration precision, StorageClass, Id type, const char* name = nullptr,
Id initializer = NoResult);
// Create an intermediate with an undefined value.
Id createUndefined(Id type);
// Store into an Id and return the l-value
void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
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
Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
Id createLoad(Id lValue, spv::Decoration precision,
spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
// Create an OpAccessChain instruction
Id createAccessChain(StorageClass, Id base, const std::vector<Id>& offsets);
@ -495,7 +541,7 @@ public:
// recursion stack can hold the memory for it.
//
void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector<int>& caseValues,
const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB); // return argument
const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB);
// Add a branch to the innermost switch's merge block.
void addSwitchBreak();
@ -512,7 +558,7 @@ public:
Block &head, &body, &merge, &continue_target;
private:
LoopBlocks();
LoopBlocks& operator=(const LoopBlocks&);
LoopBlocks& operator=(const LoopBlocks&) = delete;
};
// Start a new loop and prepare the builder to generate code for it. Until
@ -569,10 +615,13 @@ public:
std::vector<Id> indexChain;
Id instr; // cache the instruction that generates this access chain
std::vector<unsigned> swizzle; // each std::vector element selects the next GLSL component number
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 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
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.
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 {
@ -583,15 +632,22 @@ public:
CoherentFlags operator |=(const CoherentFlags &other) { return *this; }
#else
bool isVolatile() const { return volatil; }
bool isNonUniform() const { return nonUniform; }
bool anyCoherent() const {
return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent ||
subgroupcoherent || shadercallcoherent;
}
unsigned coherent : 1;
unsigned devicecoherent : 1;
unsigned queuefamilycoherent : 1;
unsigned workgroupcoherent : 1;
unsigned subgroupcoherent : 1;
unsigned shadercallcoherent : 1;
unsigned nonprivate : 1;
unsigned volatil : 1;
unsigned isImage : 1;
unsigned nonUniform : 1;
void clear() {
coherent = 0;
@ -599,9 +655,11 @@ public:
queuefamilycoherent = 0;
workgroupcoherent = 0;
subgroupcoherent = 0;
shadercallcoherent = 0;
nonprivate = 0;
volatil = 0;
isImage = 0;
nonUniform = 0;
}
CoherentFlags operator |=(const CoherentFlags &other) {
@ -610,9 +668,11 @@ public:
queuefamilycoherent |= other.queuefamilycoherent;
workgroupcoherent |= other.workgroupcoherent;
subgroupcoherent |= other.subgroupcoherent;
shadercallcoherent |= other.shadercallcoherent;
nonprivate |= other.nonprivate;
volatil |= other.volatil;
isImage |= other.isImage;
nonUniform |= other.nonUniform;
return *this;
}
#endif
@ -655,11 +715,13 @@ public:
}
// push new swizzle onto the end of any existing swizzle, merging into a single swizzle
void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment);
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
// non-trivial swizzle or no swizzle
void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags,
unsigned int alignment)
{
if (accessChain.swizzle.size() != 1) {
accessChain.component = component;
@ -671,10 +733,19 @@ public:
}
// use accessChain and swizzle to store value
void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
void accessChainStore(Id rvalue, Decoration nonUniform,
spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
// use accessChain and swizzle to load an r-value
Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
Id accessChainLoad(Decoration precision, Decoration l_nonUniform, Decoration r_nonUniform, Id ResultType,
spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax,
unsigned int alignment = 0);
// Return whether or not the access chain can be represented in SPIR-V
// as an l-value.
// E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be.
bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; }
// get the direct pointer for an l-value
Id accessChainGetLValue();
@ -703,7 +774,8 @@ public:
void createBranch(Block* block);
void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, const std::vector<unsigned int>& operands);
void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control,
const std::vector<unsigned int>& operands);
// Sets to generate opcode for specialization constants.
void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; }
@ -729,7 +801,8 @@ public:
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 dumpModuleProcesses(std::vector<unsigned int>&) const;
spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const;
spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc)
const;
unsigned int spvVersion; // the version of SPIR-V to emit in the header
SourceLanguage source;
@ -764,10 +837,16 @@ public:
std::vector<std::unique_ptr<Instruction> > externals;
std::vector<std::unique_ptr<Function> > functions;
// not output, internally used for quick & dirty canonical (unique) creation
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedConstants; // map type opcodes to constant inst.
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants; // map struct-id to constant instructions
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes; // map type opcodes to type instructions
// not output, internally used for quick & dirty canonical (unique) creation
// map type opcodes to constant inst.
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedConstants;
// map struct-id to constant instructions
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants;
// map type opcodes to type instructions
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes;
// list of OpConstantNull instructions
std::vector<Instruction*> nullConstants;
// stack of switches
std::stack<Block*> switchMerges;

View file

@ -44,10 +44,8 @@
#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"
@ -113,8 +111,6 @@ void Builder::postProcessType(const Instruction& inst, Id typeId)
}
}
break;
case OpAccessChain:
case OpPtrAccessChain:
case OpCopyObject:
break;
case OpFConvert:
@ -161,26 +157,43 @@ void Builder::postProcessType(const Instruction& inst, Id typeId)
switch (inst.getImmediateOperand(1)) {
case GLSLstd450Frexp:
case GLSLstd450FrexpStruct:
if (getSpvVersion() < glslang::EShTargetSpv_1_3 && containsType(typeId, OpTypeInt, 16))
if (getSpvVersion() < spv::Spv_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))
if (getSpvVersion() < spv::Spv_1_3 && containsType(typeId, OpTypeFloat, 16))
addExtension(spv::E_SPV_AMD_gpu_shader_half_float);
break;
default:
break;
}
break;
case OpAccessChain:
case OpPtrAccessChain:
if (isPointerType(typeId))
break;
if (basicTypeOp == OpTypeInt) {
if (width == 16)
addCapability(CapabilityInt16);
else if (width == 8)
addCapability(CapabilityInt8);
}
default:
if (basicTypeOp == OpTypeFloat && width == 16)
addCapability(CapabilityFloat16);
if (basicTypeOp == OpTypeInt && width == 16)
addCapability(CapabilityInt16);
if (basicTypeOp == OpTypeInt && width == 8)
addCapability(CapabilityInt8);
if (basicTypeOp == OpTypeInt) {
if (width == 16)
addCapability(CapabilityInt16);
else if (width == 8)
addCapability(CapabilityInt8);
else if (width == 64)
addCapability(CapabilityInt64);
} else if (basicTypeOp == OpTypeFloat) {
if (width == 16)
addCapability(CapabilityFloat16);
else if (width == 64)
addCapability(CapabilityFloat64);
}
break;
}
}
@ -436,6 +449,38 @@ void Builder::postProcessFeatures() {
}
}
}
// If any Vulkan memory model-specific functionality is used, update the
// OpMemoryModel to match.
if (capabilities.find(spv::CapabilityVulkanMemoryModelKHR) != capabilities.end()) {
memoryModel = spv::MemoryModelVulkanKHR;
addIncorporatedExtension(spv::E_SPV_KHR_vulkan_memory_model, spv::Spv_1_5);
}
// Add Aliased decoration if there's more than one Workgroup Block variable.
if (capabilities.find(spv::CapabilityWorkgroupMemoryExplicitLayoutKHR) != capabilities.end()) {
assert(entryPoints.size() == 1);
auto &ep = entryPoints[0];
std::vector<Id> workgroup_variables;
for (int i = 0; i < (int)ep->getNumOperands(); i++) {
if (!ep->isIdOperand(i))
continue;
const Id id = ep->getIdOperand(i);
const Instruction *instr = module.getInstruction(id);
if (instr->getOpCode() != spv::OpVariable)
continue;
if (instr->getImmediateOperand(0) == spv::StorageClassWorkgroup)
workgroup_variables.push_back(id);
}
if (workgroup_variables.size() > 1) {
for (size_t i = 0; i < workgroup_variables.size(); i++)
addDecoration(workgroup_variables[i], spv::DecorationAliased);
}
}
}
#endif

View file

@ -1,6 +1,6 @@
//
// Copyright (C) 2014-2016 LunarG, Inc.
// Copyright (C) 2018 Google, Inc.
// Copyright (C) 2018-2020 Google, Inc.
//
// All rights reserved.
//
@ -44,7 +44,6 @@
#include "SpvTools.h"
#include "spirv-tools/optimizer.hpp"
#include "spirv-tools/libspirv.h"
namespace glslang {
@ -67,6 +66,10 @@ spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLog
logger->missingFunctionality("Target version for SPIRV-Tools validator");
return spv_target_env::SPV_ENV_VULKAN_1_1;
}
case glslang::EShTargetVulkan_1_2:
return spv_target_env::SPV_ENV_VULKAN_1_2;
case glslang::EShTargetVulkan_1_3:
return spv_target_env::SPV_ENV_VULKAN_1_3;
default:
break;
}
@ -78,12 +81,52 @@ spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLog
return spv_target_env::SPV_ENV_UNIVERSAL_1_0;
}
// Callback passed to spvtools::Optimizer::SetMessageConsumer
void OptimizerMesssageConsumer(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;
}
// Use the SPIRV-Tools disassembler to print SPIR-V.
// Use the SPIRV-Tools disassembler to print SPIR-V using a SPV_ENV_UNIVERSAL_1_3 environment.
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv)
{
SpirvToolsDisassemble(out, spirv, spv_target_env::SPV_ENV_UNIVERSAL_1_3);
}
// Use the SPIRV-Tools disassembler to print SPIR-V with a provided SPIR-V environment.
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv,
spv_target_env requested_context)
{
// disassemble
spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_3);
spv_context context = spvContextCreate(requested_context);
spv_text text;
spv_diagnostic diagnostic = nullptr;
spvBinaryToText(context, spirv.data(), spirv.size(),
@ -112,6 +155,8 @@ void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<
spv_validator_options options = spvValidatorOptionsCreate();
spvValidatorOptionsSetRelaxBlockLayout(options, intermediate.usingHlslOffsets());
spvValidatorOptionsSetBeforeHlslLegalization(options, prelegalization);
spvValidatorOptionsSetScalarBlockLayout(options, intermediate.usingScalarBlockLayout());
spvValidatorOptionsSetWorkgroupScalarBlockLayout(options, intermediate.usingScalarBlockLayout());
spvValidateWithOptions(context, options, &binary, &diagnostic);
// report
@ -126,52 +171,21 @@ void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<
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)
// Apply the SPIRV-Tools optimizer to generated SPIR-V. HLSL SPIR-V is legalized in the process.
void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger* logger, const SpvOptions* options)
{
spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
spv_target_env target_env = MapToSpirvToolsEnv(intermediate.getSpv(), logger);
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;
});
optimizer.SetMessageConsumer(OptimizerMesssageConsumer);
// 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());
if (options->stripDebugInfo) {
optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
}
optimizer.RegisterPass(spvtools::CreateWrapOpKillPass());
optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass());
@ -195,17 +209,36 @@ void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector<unsigned int>
optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
optimizer.RegisterPass(spvtools::CreateVectorDCEPass());
optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass());
optimizer.RegisterPass(spvtools::CreateInterpolateFixupPass());
if (options->optimizeSize) {
optimizer.RegisterPass(spvtools::CreateRedundancyEliminationPass());
optimizer.RegisterPass(spvtools::CreateEliminateDeadInputComponentsPass());
}
optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
optimizer.RegisterPass(spvtools::CreateCFGCleanupPass());
if (options->generateDebugInfo) {
optimizer.RegisterPass(spvtools::CreateRedundantLineInfoElimPass());
}
spvtools::OptimizerOptions spvOptOptions;
spvOptOptions.set_run_validator(false); // The validator may run as a seperate step later on
optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on
optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
}
// Apply the SPIRV-Tools optimizer to strip debug info from SPIR-V. This is implicitly done by
// SpirvToolsTransform if spvOptions->stripDebugInfo is set, but can be called separately if
// optimization is disabled.
void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate,
std::vector<unsigned int>& spirv, spv::SpvBuildLogger* logger)
{
spv_target_env target_env = MapToSpirvToolsEnv(intermediate.getSpv(), logger);
spvtools::Optimizer optimizer(target_env);
optimizer.SetMessageConsumer(OptimizerMesssageConsumer);
optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
spvtools::OptimizerOptions spvOptOptions;
optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on
optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
}

View file

@ -41,9 +41,10 @@
#ifndef GLSLANG_SPV_TOOLS_H
#define GLSLANG_SPV_TOOLS_H
#ifdef ENABLE_OPT
#if ENABLE_OPT
#include <vector>
#include <ostream>
#include "spirv-tools/libspirv.h"
#endif
#include "glslang/MachineIndependent/localintermediate.h"
@ -52,28 +53,38 @@
namespace glslang {
struct SpvOptions {
SpvOptions() : generateDebugInfo(false), disableOptimizer(true),
SpvOptions() : generateDebugInfo(false), stripDebugInfo(false), disableOptimizer(true),
optimizeSize(false), disassemble(false), validate(false) { }
bool generateDebugInfo;
bool stripDebugInfo;
bool disableOptimizer;
bool optimizeSize;
bool disassemble;
bool validate;
};
#ifdef ENABLE_OPT
#if ENABLE_OPT
// Use the SPIRV-Tools disassembler to print SPIR-V.
// Use the SPIRV-Tools disassembler to print SPIR-V using a SPV_ENV_UNIVERSAL_1_3 environment.
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv);
// Use the SPIRV-Tools disassembler to print SPIR-V with a provided SPIR-V environment.
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv,
spv_target_env requested_context);
// Apply the SPIRV-Tools validator to generated SPIR-V.
void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger*, bool prelegalization);
// 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*);
// Apply the SPIRV-Tools optimizer to generated SPIR-V. HLSL SPIR-V is legalized in the process.
void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger*, const SpvOptions*);
// Apply the SPIRV-Tools optimizer to strip debug info from SPIR-V. This is implicitly done by
// SpirvToolsTransform if spvOptions->stripDebugInfo is set, but can be called separately if
// optimization is disabled.
void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate,
std::vector<unsigned int>& spirv, spv::SpvBuildLogger*);
#endif

View file

@ -43,10 +43,10 @@
#include <stack>
#include <sstream>
#include <cstring>
#include <utility>
#include "disassemble.h"
#include "doc.h"
#include "SpvTools.h"
namespace spv {
extern "C" {
@ -75,6 +75,7 @@ enum ExtInstSet {
GLSLextAMDInst,
GLSLextNVInst,
OpenCLExtInst,
NonSemanticDebugPrintfExtInst,
};
// Container class for a single instance of a SPIR-V stream, with methods for disassembly.
@ -100,6 +101,7 @@ protected:
void outputMask(OperandClass operandClass, unsigned mask);
void disassembleImmediates(int numOperands);
void disassembleIds(int numOperands);
std::pair<int, std::string> decodeString();
int disassembleString();
void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands);
@ -290,31 +292,44 @@ void SpirvStream::disassembleIds(int numOperands)
}
}
// return the number of operands consumed by the string
int SpirvStream::disassembleString()
// decode string from words at current position (non-consuming)
std::pair<int, std::string> SpirvStream::decodeString()
{
int startWord = word;
out << " \"";
const char* wordString;
std::string res;
int wordPos = word;
char c;
bool done = false;
do {
unsigned int content = stream[word];
wordString = (const char*)&content;
unsigned int content = stream[wordPos];
for (int charCount = 0; charCount < 4; ++charCount) {
if (*wordString == 0) {
c = content & 0xff;
content >>= 8;
if (c == '\0') {
done = true;
break;
}
out << *(wordString++);
res += c;
}
++word;
} while (! done);
++wordPos;
} while(! done);
return std::make_pair(wordPos - word, res);
}
// return the number of operands consumed by the string
int SpirvStream::disassembleString()
{
out << " \"";
std::pair<int, std::string> decoderes = decodeString();
out << decoderes.second;
out << "\"";
return word - startWord;
word += decoderes.first;
return decoderes.first;
}
void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands)
@ -331,7 +346,7 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
nextNestedControl = 0;
}
} else if (opCode == OpExtInstImport) {
idDescriptor[resultId] = (const char*)(&stream[word]);
idDescriptor[resultId] = decodeString().second;
}
else {
if (resultId != 0 && idDescriptor[resultId].size() == 0) {
@ -428,7 +443,7 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
--numOperands;
// Get names for printing "(XXX)" for readability, *after* this id
if (opCode == OpName)
idDescriptor[stream[word - 1]] = (const char*)(&stream[word]);
idDescriptor[stream[word - 1]] = decodeString().second;
break;
case OperandVariableIds:
disassembleIds(numOperands);
@ -480,8 +495,12 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
if (opCode == OpExtInst) {
ExtInstSet extInstSet = GLSL450Inst;
const char* name = idDescriptor[stream[word - 2]].c_str();
if (0 == memcmp("OpenCL", name, 6)) {
if (strcmp("OpenCL.std", name) == 0) {
extInstSet = OpenCLExtInst;
} else if (strcmp("OpenCL.DebugInfo.100", name) == 0) {
extInstSet = OpenCLExtInst;
} else if (strcmp("NonSemantic.DebugPrintf", name) == 0) {
extInstSet = NonSemanticDebugPrintfExtInst;
} 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 ||
@ -505,6 +524,8 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
}
else if (extInstSet == GLSLextNVInst) {
out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")";
} else if (extInstSet == NonSemanticDebugPrintfExtInst) {
out << "(DebugPrintf)";
}
}
break;
@ -512,6 +533,10 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
case OperandLiteralString:
numOperands -= disassembleString();
break;
case OperandVariableLiteralStrings:
while (numOperands > 0)
numOperands -= disassembleString();
return;
case OperandMemoryAccess:
outputMask(OperandMemoryAccess, stream[word++]);
--numOperands;

View file

@ -1,5 +1,6 @@
//
// Copyright (C) 2014-2015 LunarG, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@ -99,12 +100,12 @@ const char* ExecutionModelString(int model)
default: return "Bad";
case ExecutionModelRayGenerationNV: return "RayGenerationNV";
case ExecutionModelIntersectionNV: return "IntersectionNV";
case ExecutionModelAnyHitNV: return "AnyHitNV";
case ExecutionModelClosestHitNV: return "ClosestHitNV";
case ExecutionModelMissNV: return "MissNV";
case ExecutionModelCallableNV: return "CallableNV";
case ExecutionModelRayGenerationKHR: return "RayGenerationKHR";
case ExecutionModelIntersectionKHR: return "IntersectionKHR";
case ExecutionModelAnyHitKHR: return "AnyHitKHR";
case ExecutionModelClosestHitKHR: return "ClosestHitKHR";
case ExecutionModelMissKHR: return "MissKHR";
case ExecutionModelCallableKHR: return "CallableKHR";
}
}
@ -133,7 +134,7 @@ const char* MemoryString(int mem)
}
}
const int ExecutionModeCeiling = 33;
const int ExecutionModeCeiling = 40;
const char* ExecutionModeString(int mode)
{
@ -172,7 +173,22 @@ const char* ExecutionModeString(int mode)
case 31: return "ContractionOff";
case 32: return "Bad";
case 4446: return "PostDepthCoverage";
case ExecutionModeInitializer: return "Initializer";
case ExecutionModeFinalizer: return "Finalizer";
case ExecutionModeSubgroupSize: return "SubgroupSize";
case ExecutionModeSubgroupsPerWorkgroup: return "SubgroupsPerWorkgroup";
case ExecutionModeSubgroupsPerWorkgroupId: return "SubgroupsPerWorkgroupId";
case ExecutionModeLocalSizeId: return "LocalSizeId";
case ExecutionModeLocalSizeHintId: return "LocalSizeHintId";
case ExecutionModePostDepthCoverage: return "PostDepthCoverage";
case ExecutionModeDenormPreserve: return "DenormPreserve";
case ExecutionModeDenormFlushToZero: return "DenormFlushToZero";
case ExecutionModeSignedZeroInfNanPreserve: return "SignedZeroInfNanPreserve";
case ExecutionModeRoundingModeRTE: return "RoundingModeRTE";
case ExecutionModeRoundingModeRTZ: return "RoundingModeRTZ";
case ExecutionModeStencilRefReplacingEXT: return "StencilRefReplacingEXT";
case ExecutionModeSubgroupUniformControlFlowKHR: return "SubgroupUniformControlFlow";
case ExecutionModeOutputLinesNV: return "OutputLinesNV";
case ExecutionModeOutputPrimitivesNV: return "OutputPrimitivesNV";
@ -187,6 +203,11 @@ const char* ExecutionModeString(int mode)
case ExecutionModeShadingRateInterlockOrderedEXT: return "ShadingRateInterlockOrderedEXT";
case ExecutionModeShadingRateInterlockUnorderedEXT: return "ShadingRateInterlockUnorderedEXT";
case ExecutionModeMaxWorkgroupSizeINTEL: return "MaxWorkgroupSizeINTEL";
case ExecutionModeMaxWorkDimINTEL: return "MaxWorkDimINTEL";
case ExecutionModeNoGlobalOffsetINTEL: return "NoGlobalOffsetINTEL";
case ExecutionModeNumSIMDWorkitemsINTEL: return "NumSIMDWorkitemsINTEL";
case ExecutionModeCeiling:
default: return "Bad";
}
@ -209,12 +230,12 @@ const char* StorageClassString(int StorageClass)
case 11: return "Image";
case 12: return "StorageBuffer";
case StorageClassRayPayloadNV: return "RayPayloadNV";
case StorageClassHitAttributeNV: return "HitAttributeNV";
case StorageClassIncomingRayPayloadNV: return "IncomingRayPayloadNV";
case StorageClassShaderRecordBufferNV: return "ShaderRecordBufferNV";
case StorageClassCallableDataNV: return "CallableDataNV";
case StorageClassIncomingCallableDataNV: return "IncomingCallableDataNV";
case StorageClassRayPayloadKHR: return "RayPayloadKHR";
case StorageClassHitAttributeKHR: return "HitAttributeKHR";
case StorageClassIncomingRayPayloadKHR: return "IncomingRayPayloadKHR";
case StorageClassShaderRecordBufferKHR: return "ShaderRecordBufferKHR";
case StorageClassCallableDataKHR: return "CallableDataKHR";
case StorageClassIncomingCallableDataKHR: return "IncomingCallableDataKHR";
case StorageClassPhysicalStorageBufferEXT: return "PhysicalStorageBufferEXT";
@ -284,7 +305,8 @@ const char* DecorationString(int decoration)
case DecorationPerPrimitiveNV: return "PerPrimitiveNV";
case DecorationPerViewNV: return "PerViewNV";
case DecorationPerTaskNV: return "PerTaskNV";
case DecorationPerVertexNV: return "PerVertexNV";
case DecorationPerVertexKHR: return "PerVertexKHR";
case DecorationNonUniformEXT: return "DecorationNonUniformEXT";
case DecorationHlslCounterBufferGOOGLE: return "DecorationHlslCounterBufferGOOGLE";
@ -352,6 +374,8 @@ const char* BuiltInString(int builtIn)
case 4424: return "BaseVertex";
case 4425: return "BaseInstance";
case 4426: return "DrawIndex";
case 4432: return "PrimitiveShadingRateKHR";
case 4444: return "ShadingRateKHR";
case 5014: return "FragStencilRefEXT";
case 4992: return "BaryCoordNoPerspAMD";
@ -361,32 +385,34 @@ const char* BuiltInString(int builtIn)
case 4996: return "BaryCoordSmoothCentroidAMD";
case 4997: return "BaryCoordSmoothSampleAMD";
case 4998: return "BaryCoordPullModelAMD";
case BuiltInLaunchIdNV: return "LaunchIdNV";
case BuiltInLaunchSizeNV: return "LaunchSizeNV";
case BuiltInWorldRayOriginNV: return "WorldRayOriginNV";
case BuiltInWorldRayDirectionNV: return "WorldRayDirectionNV";
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 BuiltInLaunchIdKHR: return "LaunchIdKHR";
case BuiltInLaunchSizeKHR: return "LaunchSizeKHR";
case BuiltInWorldRayOriginKHR: return "WorldRayOriginKHR";
case BuiltInWorldRayDirectionKHR: return "WorldRayDirectionKHR";
case BuiltInObjectRayOriginKHR: return "ObjectRayOriginKHR";
case BuiltInObjectRayDirectionKHR: return "ObjectRayDirectionKHR";
case BuiltInRayTminKHR: return "RayTminKHR";
case BuiltInRayTmaxKHR: return "RayTmaxKHR";
case BuiltInCullMaskKHR: return "CullMaskKHR";
case BuiltInInstanceCustomIndexKHR: return "InstanceCustomIndexKHR";
case BuiltInRayGeometryIndexKHR: return "RayGeometryIndexKHR";
case BuiltInObjectToWorldKHR: return "ObjectToWorldKHR";
case BuiltInWorldToObjectKHR: return "WorldToObjectKHR";
case BuiltInHitTNV: return "HitTNV";
case BuiltInHitKindKHR: return "HitKindKHR";
case BuiltInIncomingRayFlagsKHR: return "IncomingRayFlagsKHR";
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";
case BuiltInBaryCoordKHR: return "BaryCoordKHR";
case BuiltInBaryCoordNoPerspKHR: return "BaryCoordNoPerspKHR";
case BuiltInFragSizeEXT: return "FragSizeEXT";
case BuiltInFragInvocationCountEXT: return "FragInvocationCountEXT";
case BuiltInFragSizeEXT: return "FragSizeEXT";
case BuiltInFragInvocationCountEXT: return "FragInvocationCountEXT";
case 5264: return "FullyCoveredEXT";
@ -402,6 +428,7 @@ const char* BuiltInString(int builtIn)
case BuiltInSMCountNV: return "SMCountNV";
case BuiltInWarpIDNV: return "WarpIDNV";
case BuiltInSMIDNV: return "SMIDNV";
case BuiltInCurrentRayTimeNV: return "CurrentRayTimeNV";
default: return "Bad";
}
@ -500,6 +527,8 @@ const char* ImageFormatString(int format)
case 37: return "Rg8ui";
case 38: return "R16ui";
case 39: return "R8ui";
case 40: return "R64ui";
case 41: return "R64i";
default:
return "Bad";
@ -873,6 +902,12 @@ const char* CapabilityString(int info)
case CapabilityDeviceGroup: return "DeviceGroup";
case CapabilityMultiView: return "MultiView";
case CapabilityDenormPreserve: return "DenormPreserve";
case CapabilityDenormFlushToZero: return "DenormFlushToZero";
case CapabilitySignedZeroInfNanPreserve: return "SignedZeroInfNanPreserve";
case CapabilityRoundingModeRTE: return "RoundingModeRTE";
case CapabilityRoundingModeRTZ: return "RoundingModeRTZ";
case CapabilityStencilExportEXT: return "StencilExportEXT";
case CapabilityFloat16ImageAMD: return "Float16ImageAMD";
@ -890,9 +925,15 @@ const char* CapabilityString(int info)
case CapabilityPerViewAttributesNV: return "PerViewAttributesNV";
case CapabilityGroupNonUniformPartitionedNV: return "GroupNonUniformPartitionedNV";
case CapabilityRayTracingNV: return "RayTracingNV";
case CapabilityRayTracingMotionBlurNV: return "RayTracingMotionBlurNV";
case CapabilityRayTracingKHR: return "RayTracingKHR";
case CapabilityRayCullMaskKHR: return "RayCullMaskKHR";
case CapabilityRayQueryKHR: return "RayQueryKHR";
case CapabilityRayTracingProvisionalKHR: return "RayTracingProvisionalKHR";
case CapabilityRayTraversalPrimitiveCullingKHR: return "RayTraversalPrimitiveCullingKHR";
case CapabilityComputeDerivativeGroupQuadsNV: return "ComputeDerivativeGroupQuadsNV";
case CapabilityComputeDerivativeGroupLinearNV: return "ComputeDerivativeGroupLinearNV";
case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV";
case CapabilityFragmentBarycentricKHR: return "FragmentBarycentricKHR";
case CapabilityMeshShadingNV: return "MeshShadingNV";
case CapabilityImageFootprintNV: return "ImageFootprintNV";
// case CapabilityShadingRateNV: return "ShadingRateNV"; // superseded by FragmentDensityEXT
@ -928,11 +969,25 @@ const char* CapabilityString(int info)
case CapabilityFragmentShaderPixelInterlockEXT: return "CapabilityFragmentShaderPixelInterlockEXT";
case CapabilityFragmentShaderShadingRateInterlockEXT: return "CapabilityFragmentShaderShadingRateInterlockEXT";
case CapabilityFragmentShadingRateKHR: return "FragmentShadingRateKHR";
case CapabilityDemoteToHelperInvocationEXT: return "DemoteToHelperInvocationEXT";
case CapabilityShaderClockKHR: return "ShaderClockKHR";
case CapabilityInt64ImageEXT: return "Int64ImageEXT";
case CapabilityIntegerFunctions2INTEL: return "CapabilityIntegerFunctions2INTEL";
case CapabilityAtomicFloat16AddEXT: return "AtomicFloat16AddEXT";
case CapabilityAtomicFloat32AddEXT: return "AtomicFloat32AddEXT";
case CapabilityAtomicFloat64AddEXT: return "AtomicFloat64AddEXT";
case CapabilityAtomicFloat16MinMaxEXT: return "AtomicFloat16MinMaxEXT";
case CapabilityAtomicFloat32MinMaxEXT: return "AtomicFloat32MinMaxEXT";
case CapabilityAtomicFloat64MinMaxEXT: return "AtomicFloat64MinMaxEXT";
case CapabilityWorkgroupMemoryExplicitLayoutKHR: return "CapabilityWorkgroupMemoryExplicitLayoutKHR";
case CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR: return "CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR";
case CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR: return "CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR";
default: return "Bad";
}
}
@ -1264,6 +1319,7 @@ const char* OpcodeString(int op)
case 320: return "OpImageSparseRead";
case OpModuleProcessed: return "OpModuleProcessed";
case OpExecutionModeId: return "OpExecutionModeId";
case OpDecorateId: return "OpDecorateId";
case 333: return "OpGroupNonUniformElect";
@ -1301,6 +1357,8 @@ const char* OpcodeString(int op)
case 365: return "OpGroupNonUniformQuadBroadcast";
case 366: return "OpGroupNonUniformQuadSwap";
case OpTerminateInvocation: return "OpTerminateInvocation";
case 4421: return "OpSubgroupBallotKHR";
case 4422: return "OpSubgroupFirstInvocationKHR";
case 4428: return "OpSubgroupAllKHR";
@ -1308,6 +1366,10 @@ const char* OpcodeString(int op)
case 4430: return "OpSubgroupAllEqualKHR";
case 4432: return "OpSubgroupReadInvocationKHR";
case OpAtomicFAddEXT: return "OpAtomicFAddEXT";
case OpAtomicFMinEXT: return "OpAtomicFMinEXT";
case OpAtomicFMaxEXT: return "OpAtomicFMaxEXT";
case 5000: return "OpGroupIAddNonUniformAMD";
case 5001: return "OpGroupFAddNonUniformAMD";
case 5002: return "OpGroupFMinNonUniformAMD";
@ -1325,16 +1387,48 @@ const char* OpcodeString(int op)
case OpDecorateStringGOOGLE: return "OpDecorateStringGOOGLE";
case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE";
case OpReportIntersectionKHR: return "OpReportIntersectionKHR";
case OpIgnoreIntersectionNV: return "OpIgnoreIntersectionNV";
case OpIgnoreIntersectionKHR: return "OpIgnoreIntersectionKHR";
case OpTerminateRayNV: return "OpTerminateRayNV";
case OpTerminateRayKHR: return "OpTerminateRayKHR";
case OpTraceNV: return "OpTraceNV";
case OpTraceRayMotionNV: return "OpTraceRayMotionNV";
case OpTraceRayKHR: return "OpTraceRayKHR";
case OpTypeAccelerationStructureKHR: return "OpTypeAccelerationStructureKHR";
case OpExecuteCallableNV: return "OpExecuteCallableNV";
case OpExecuteCallableKHR: return "OpExecuteCallableKHR";
case OpConvertUToAccelerationStructureKHR: return "OpConvertUToAccelerationStructureKHR";
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";
case OpTypeRayQueryKHR: return "OpTypeRayQueryKHR";
case OpRayQueryInitializeKHR: return "OpRayQueryInitializeKHR";
case OpRayQueryTerminateKHR: return "OpRayQueryTerminateKHR";
case OpRayQueryGenerateIntersectionKHR: return "OpRayQueryGenerateIntersectionKHR";
case OpRayQueryConfirmIntersectionKHR: return "OpRayQueryConfirmIntersectionKHR";
case OpRayQueryProceedKHR: return "OpRayQueryProceedKHR";
case OpRayQueryGetIntersectionTypeKHR: return "OpRayQueryGetIntersectionTypeKHR";
case OpRayQueryGetRayTMinKHR: return "OpRayQueryGetRayTMinKHR";
case OpRayQueryGetRayFlagsKHR: return "OpRayQueryGetRayFlagsKHR";
case OpRayQueryGetIntersectionTKHR: return "OpRayQueryGetIntersectionTKHR";
case OpRayQueryGetIntersectionInstanceCustomIndexKHR: return "OpRayQueryGetIntersectionInstanceCustomIndexKHR";
case OpRayQueryGetIntersectionInstanceIdKHR: return "OpRayQueryGetIntersectionInstanceIdKHR";
case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: return "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR";
case OpRayQueryGetIntersectionGeometryIndexKHR: return "OpRayQueryGetIntersectionGeometryIndexKHR";
case OpRayQueryGetIntersectionPrimitiveIndexKHR: return "OpRayQueryGetIntersectionPrimitiveIndexKHR";
case OpRayQueryGetIntersectionBarycentricsKHR: return "OpRayQueryGetIntersectionBarycentricsKHR";
case OpRayQueryGetIntersectionFrontFaceKHR: return "OpRayQueryGetIntersectionFrontFaceKHR";
case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: return "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR";
case OpRayQueryGetIntersectionObjectRayDirectionKHR: return "OpRayQueryGetIntersectionObjectRayDirectionKHR";
case OpRayQueryGetIntersectionObjectRayOriginKHR: return "OpRayQueryGetIntersectionObjectRayOriginKHR";
case OpRayQueryGetWorldRayDirectionKHR: return "OpRayQueryGetWorldRayDirectionKHR";
case OpRayQueryGetWorldRayOriginKHR: return "OpRayQueryGetWorldRayOriginKHR";
case OpRayQueryGetIntersectionObjectToWorldKHR: return "OpRayQueryGetIntersectionObjectToWorldKHR";
case OpRayQueryGetIntersectionWorldToObjectKHR: return "OpRayQueryGetIntersectionWorldToObjectKHR";
case OpTypeCooperativeMatrixNV: return "OpTypeCooperativeMatrixNV";
case OpCooperativeMatrixLoadNV: return "OpCooperativeMatrixLoadNV";
case OpCooperativeMatrixStoreNV: return "OpCooperativeMatrixStoreNV";
@ -1388,6 +1482,7 @@ void Parameterize()
InstructionDesc[OpMemoryModel].setResultAndType(false, false);
InstructionDesc[OpEntryPoint].setResultAndType(false, false);
InstructionDesc[OpExecutionMode].setResultAndType(false, false);
InstructionDesc[OpExecutionModeId].setResultAndType(false, false);
InstructionDesc[OpTypeVoid].setResultAndType(true, false);
InstructionDesc[OpTypeBool].setResultAndType(true, false);
InstructionDesc[OpTypeInt].setResultAndType(true, false);
@ -1441,6 +1536,7 @@ void Parameterize()
InstructionDesc[OpBranchConditional].setResultAndType(false, false);
InstructionDesc[OpSwitch].setResultAndType(false, false);
InstructionDesc[OpKill].setResultAndType(false, false);
InstructionDesc[OpTerminateInvocation].setResultAndType(false, false);
InstructionDesc[OpReturn].setResultAndType(false, false);
InstructionDesc[OpReturnValue].setResultAndType(false, false);
InstructionDesc[OpUnreachable].setResultAndType(false, false);
@ -1574,6 +1670,10 @@ void Parameterize()
InstructionDesc[OpExecutionMode].operands.push(OperandExecutionMode, "'Mode'");
InstructionDesc[OpExecutionMode].operands.push(OperandOptionalLiteral, "See <<Execution_Mode,Execution Mode>>");
InstructionDesc[OpExecutionModeId].operands.push(OperandId, "'Entry Point'");
InstructionDesc[OpExecutionModeId].operands.push(OperandExecutionMode, "'Mode'");
InstructionDesc[OpExecutionModeId].operands.push(OperandVariableIds, "See <<Execution_Mode,Execution Mode>>");
InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Width'");
InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Signedness'");
@ -1667,7 +1767,7 @@ void Parameterize()
InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandId, "'Target'");
InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandDecoration, "");
InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandLiteralString, "'Literal String'");
InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandVariableLiteralStrings, "'Literal Strings'");
InstructionDesc[OpMemberDecorate].operands.push(OperandId, "'Structure Type'");
InstructionDesc[OpMemberDecorate].operands.push(OperandLiteralNumber, "'Member'");
@ -1677,7 +1777,7 @@ void Parameterize()
InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandId, "'Structure Type'");
InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandLiteralNumber, "'Member'");
InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandDecoration, "");
InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandLiteralString, "'Literal String'");
InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandVariableLiteralStrings, "'Literal Strings'");
InstructionDesc[OpGroupDecorate].operands.push(OperandId, "'Decoration Group'");
InstructionDesc[OpGroupDecorate].operands.push(OperandVariableIds, "'Targets'");
@ -2230,6 +2330,11 @@ void Parameterize()
InstructionDesc[OpAtomicIAdd].operands.push(OperandMemorySemantics, "'Semantics'");
InstructionDesc[OpAtomicIAdd].operands.push(OperandId, "'Value'");
InstructionDesc[OpAtomicFAddEXT].operands.push(OperandId, "'Pointer'");
InstructionDesc[OpAtomicFAddEXT].operands.push(OperandScope, "'Scope'");
InstructionDesc[OpAtomicFAddEXT].operands.push(OperandMemorySemantics, "'Semantics'");
InstructionDesc[OpAtomicFAddEXT].operands.push(OperandId, "'Value'");
InstructionDesc[OpAtomicISub].operands.push(OperandId, "'Pointer'");
InstructionDesc[OpAtomicISub].operands.push(OperandScope, "'Scope'");
InstructionDesc[OpAtomicISub].operands.push(OperandMemorySemantics, "'Semantics'");
@ -2255,6 +2360,16 @@ void Parameterize()
InstructionDesc[OpAtomicSMax].operands.push(OperandMemorySemantics, "'Semantics'");
InstructionDesc[OpAtomicSMax].operands.push(OperandId, "'Value'");
InstructionDesc[OpAtomicFMinEXT].operands.push(OperandId, "'Pointer'");
InstructionDesc[OpAtomicFMinEXT].operands.push(OperandScope, "'Scope'");
InstructionDesc[OpAtomicFMinEXT].operands.push(OperandMemorySemantics, "'Semantics'");
InstructionDesc[OpAtomicFMinEXT].operands.push(OperandId, "'Value'");
InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandId, "'Pointer'");
InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandScope, "'Scope'");
InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandMemorySemantics, "'Semantics'");
InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandId, "'Value'");
InstructionDesc[OpAtomicAnd].operands.push(OperandId, "'Pointer'");
InstructionDesc[OpAtomicAnd].operands.push(OperandScope, "'Scope'");
InstructionDesc[OpAtomicAnd].operands.push(OperandMemorySemantics, "'Semantics'");
@ -2633,7 +2748,7 @@ void Parameterize()
InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandScope, "'Execution'");
InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandId, "X");
InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandLiteralNumber, "'Direction'");
InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandId, "'Direction'");
InstructionDesc[OpSubgroupBallotKHR].operands.push(OperandId, "'Predicate'");
@ -2694,9 +2809,9 @@ void Parameterize()
InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X");
InstructionDesc[OpTypeAccelerationStructureNV].setResultAndType(true, false);
InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
InstructionDesc[OpTraceNV].operands.push(OperandId, "'NV Acceleration Structure'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Acceleration Structure'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Flags'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Cull Mask'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Offset'");
@ -2709,17 +2824,149 @@ void Parameterize()
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[OpTraceRayMotionNV].operands.push(OperandId, "'Acceleration Structure'");
InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Ray Flags'");
InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Cull Mask'");
InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'SBT Record Offset'");
InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'SBT Record Stride'");
InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Miss Index'");
InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Ray Origin'");
InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'TMin'");
InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Ray Direction'");
InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'TMax'");
InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Time'");
InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Payload'");
InstructionDesc[OpTraceRayMotionNV].setResultAndType(false, false);
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Acceleration Structure'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Flags'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Cull Mask'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Offset'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Stride'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Miss Index'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Origin'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'TMin'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Direction'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'TMax'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Payload'");
InstructionDesc[OpTraceRayKHR].setResultAndType(false, false);
InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Parameter'");
InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Kind'");
InstructionDesc[OpIgnoreIntersectionNV].setResultAndType(false, false);
InstructionDesc[OpIgnoreIntersectionKHR].setResultAndType(false, false);
InstructionDesc[OpTerminateRayNV].setResultAndType(false, false);
InstructionDesc[OpTerminateRayKHR].setResultAndType(false, false);
InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "SBT Record Index");
InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "CallableData ID");
InstructionDesc[OpExecuteCallableNV].setResultAndType(false, false);
InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "SBT Record Index");
InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "CallableData");
InstructionDesc[OpExecuteCallableKHR].setResultAndType(false, false);
InstructionDesc[OpConvertUToAccelerationStructureKHR].operands.push(OperandId, "Value");
InstructionDesc[OpConvertUToAccelerationStructureKHR].setResultAndType(true, true);
// Ray Query
InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
InstructionDesc[OpTypeRayQueryKHR].setResultAndType(true, false);
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'AccelerationS'");
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayFlags'");
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'CullMask'");
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Origin'");
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Tmin'");
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Direction'");
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Tmax'");
InstructionDesc[OpRayQueryInitializeKHR].setResultAndType(false, false);
InstructionDesc[OpRayQueryTerminateKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryTerminateKHR].setResultAndType(false, false);
InstructionDesc[OpRayQueryGenerateIntersectionKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGenerateIntersectionKHR].operands.push(OperandId, "'THit'");
InstructionDesc[OpRayQueryGenerateIntersectionKHR].setResultAndType(false, false);
InstructionDesc[OpRayQueryConfirmIntersectionKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryConfirmIntersectionKHR].setResultAndType(false, false);
InstructionDesc[OpRayQueryProceedKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryProceedKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionTypeKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionTypeKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionTypeKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetRayTMinKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetRayTMinKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetRayFlagsKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetRayFlagsKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionTKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionTKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionTKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionCandidateAABBOpaqueKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionCandidateAABBOpaqueKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetWorldRayDirectionKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetWorldRayDirectionKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetWorldRayOriginKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetWorldRayOriginKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].setResultAndType(true, true);
InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Sampled Image'");
InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Coordinate'");
InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Granularity'");

View file

@ -125,6 +125,7 @@ enum OperandClass {
OperandVariableLiteralId,
OperandLiteralNumber,
OperandLiteralString,
OperandVariableLiteralStrings,
OperandSource,
OperandExecutionModel,
OperandAddressing,

View file

@ -784,8 +784,8 @@ inline std::istream& ParseNormalFloat(std::istream& is, bool negate_value,
if (val.isInfinity()) {
// Fail the parse. Emulate standard behaviour by setting the value to
// the closest normal value, and set the fail bit on the stream.
value.set_value((value.isNegative() | negate_value) ? T::lowest()
: T::max());
value.set_value((value.isNegative() || negate_value) ? T::lowest()
: T::max());
is.setstate(std::ios_base::failbit);
}
return is;

View file

@ -1,4 +1,4 @@
// Copyright (c) 2014-2019 The Khronos Group Inc.
// Copyright (c) 2014-2020 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"),
@ -49,11 +49,11 @@ namespace spv {
typedef unsigned int Id;
#define SPV_VERSION 0x10400
#define SPV_VERSION 0x10600
#define SPV_REVISION 1
static const unsigned int MagicNumber = 0x07230203;
static const unsigned int Version = 0x00010400;
static const unsigned int Version = 0x00010600;
static const unsigned int Revision = 1;
static const unsigned int OpCodeMask = 0xffff;
static const unsigned int WordCountShift = 16;
@ -65,6 +65,7 @@ enum SourceLanguage {
SourceLanguageOpenCL_C = 3,
SourceLanguageOpenCL_CPP = 4,
SourceLanguageHLSL = 5,
SourceLanguageCPP_for_OpenCL = 6,
SourceLanguageMax = 0x7fffffff,
};
@ -78,11 +79,17 @@ enum ExecutionModel {
ExecutionModelKernel = 6,
ExecutionModelTaskNV = 5267,
ExecutionModelMeshNV = 5268,
ExecutionModelRayGenerationKHR = 5313,
ExecutionModelRayGenerationNV = 5313,
ExecutionModelIntersectionKHR = 5314,
ExecutionModelIntersectionNV = 5314,
ExecutionModelAnyHitKHR = 5315,
ExecutionModelAnyHitNV = 5315,
ExecutionModelClosestHitKHR = 5316,
ExecutionModelClosestHitNV = 5316,
ExecutionModelMissKHR = 5317,
ExecutionModelMissNV = 5317,
ExecutionModelCallableKHR = 5318,
ExecutionModelCallableNV = 5318,
ExecutionModelMax = 0x7fffffff,
};
@ -144,6 +151,7 @@ enum ExecutionMode {
ExecutionModeSubgroupsPerWorkgroupId = 37,
ExecutionModeLocalSizeId = 38,
ExecutionModeLocalSizeHintId = 39,
ExecutionModeSubgroupUniformControlFlowKHR = 4421,
ExecutionModePostDepthCoverage = 4446,
ExecutionModeDenormPreserve = 4459,
ExecutionModeDenormFlushToZero = 4460,
@ -162,6 +170,16 @@ enum ExecutionMode {
ExecutionModeSampleInterlockUnorderedEXT = 5369,
ExecutionModeShadingRateInterlockOrderedEXT = 5370,
ExecutionModeShadingRateInterlockUnorderedEXT = 5371,
ExecutionModeSharedLocalMemorySizeINTEL = 5618,
ExecutionModeRoundingModeRTPINTEL = 5620,
ExecutionModeRoundingModeRTNINTEL = 5621,
ExecutionModeFloatingPointModeALTINTEL = 5622,
ExecutionModeFloatingPointModeIEEEINTEL = 5623,
ExecutionModeMaxWorkgroupSizeINTEL = 5893,
ExecutionModeMaxWorkDimINTEL = 5894,
ExecutionModeNoGlobalOffsetINTEL = 5895,
ExecutionModeNumSIMDWorkitemsINTEL = 5896,
ExecutionModeSchedulerTargetFmaxMhzINTEL = 5903,
ExecutionModeMax = 0x7fffffff,
};
@ -179,14 +197,23 @@ enum StorageClass {
StorageClassAtomicCounter = 10,
StorageClassImage = 11,
StorageClassStorageBuffer = 12,
StorageClassCallableDataKHR = 5328,
StorageClassCallableDataNV = 5328,
StorageClassIncomingCallableDataKHR = 5329,
StorageClassIncomingCallableDataNV = 5329,
StorageClassRayPayloadKHR = 5338,
StorageClassRayPayloadNV = 5338,
StorageClassHitAttributeKHR = 5339,
StorageClassHitAttributeNV = 5339,
StorageClassIncomingRayPayloadKHR = 5342,
StorageClassIncomingRayPayloadNV = 5342,
StorageClassShaderRecordBufferKHR = 5343,
StorageClassShaderRecordBufferNV = 5343,
StorageClassPhysicalStorageBuffer = 5349,
StorageClassPhysicalStorageBufferEXT = 5349,
StorageClassCodeSectionINTEL = 5605,
StorageClassDeviceOnlyINTEL = 5936,
StorageClassHostOnlyINTEL = 5937,
StorageClassMax = 0x7fffffff,
};
@ -257,6 +284,8 @@ enum ImageFormat {
ImageFormatRg8ui = 37,
ImageFormatR16ui = 38,
ImageFormatR8ui = 39,
ImageFormatR64ui = 40,
ImageFormatR64i = 41,
ImageFormatMax = 0x7fffffff,
};
@ -324,6 +353,8 @@ enum ImageOperandsShift {
ImageOperandsVolatileTexelKHRShift = 11,
ImageOperandsSignExtendShift = 12,
ImageOperandsZeroExtendShift = 13,
ImageOperandsNontemporalShift = 14,
ImageOperandsOffsetsShift = 16,
ImageOperandsMax = 0x7fffffff,
};
@ -347,6 +378,8 @@ enum ImageOperandsMask {
ImageOperandsVolatileTexelKHRMask = 0x00000800,
ImageOperandsSignExtendMask = 0x00001000,
ImageOperandsZeroExtendMask = 0x00002000,
ImageOperandsNontemporalMask = 0x00004000,
ImageOperandsOffsetsMask = 0x00010000,
};
enum FPFastMathModeShift {
@ -355,6 +388,8 @@ enum FPFastMathModeShift {
FPFastMathModeNSZShift = 2,
FPFastMathModeAllowRecipShift = 3,
FPFastMathModeFastShift = 4,
FPFastMathModeAllowContractFastINTELShift = 16,
FPFastMathModeAllowReassocINTELShift = 17,
FPFastMathModeMax = 0x7fffffff,
};
@ -365,6 +400,8 @@ enum FPFastMathModeMask {
FPFastMathModeNSZMask = 0x00000004,
FPFastMathModeAllowRecipMask = 0x00000008,
FPFastMathModeFastMask = 0x00000010,
FPFastMathModeAllowContractFastINTELMask = 0x00010000,
FPFastMathModeAllowReassocINTELMask = 0x00020000,
};
enum FPRoundingMode {
@ -378,6 +415,7 @@ enum FPRoundingMode {
enum LinkageType {
LinkageTypeExport = 0,
LinkageTypeImport = 1,
LinkageTypeLinkOnceODR = 2,
LinkageTypeMax = 0x7fffffff,
};
@ -458,6 +496,7 @@ enum Decoration {
DecorationPerPrimitiveNV = 5271,
DecorationPerViewNV = 5272,
DecorationPerTaskNV = 5273,
DecorationPerVertexKHR = 5285,
DecorationPerVertexNV = 5285,
DecorationNonUniform = 5300,
DecorationNonUniformEXT = 5300,
@ -465,11 +504,50 @@ enum Decoration {
DecorationRestrictPointerEXT = 5355,
DecorationAliasedPointer = 5356,
DecorationAliasedPointerEXT = 5356,
DecorationBindlessSamplerNV = 5398,
DecorationBindlessImageNV = 5399,
DecorationBoundSamplerNV = 5400,
DecorationBoundImageNV = 5401,
DecorationSIMTCallINTEL = 5599,
DecorationReferencedIndirectlyINTEL = 5602,
DecorationClobberINTEL = 5607,
DecorationSideEffectsINTEL = 5608,
DecorationVectorComputeVariableINTEL = 5624,
DecorationFuncParamIOKindINTEL = 5625,
DecorationVectorComputeFunctionINTEL = 5626,
DecorationStackCallINTEL = 5627,
DecorationGlobalVariableOffsetINTEL = 5628,
DecorationCounterBuffer = 5634,
DecorationHlslCounterBufferGOOGLE = 5634,
DecorationHlslSemanticGOOGLE = 5635,
DecorationUserSemantic = 5635,
DecorationUserTypeGOOGLE = 5636,
DecorationFunctionRoundingModeINTEL = 5822,
DecorationFunctionDenormModeINTEL = 5823,
DecorationRegisterINTEL = 5825,
DecorationMemoryINTEL = 5826,
DecorationNumbanksINTEL = 5827,
DecorationBankwidthINTEL = 5828,
DecorationMaxPrivateCopiesINTEL = 5829,
DecorationSinglepumpINTEL = 5830,
DecorationDoublepumpINTEL = 5831,
DecorationMaxReplicatesINTEL = 5832,
DecorationSimpleDualPortINTEL = 5833,
DecorationMergeINTEL = 5834,
DecorationBankBitsINTEL = 5835,
DecorationForcePow2DepthINTEL = 5836,
DecorationBurstCoalesceINTEL = 5899,
DecorationCacheSizeINTEL = 5900,
DecorationDontStaticallyCoalesceINTEL = 5901,
DecorationPrefetchINTEL = 5902,
DecorationStallEnableINTEL = 5905,
DecorationFuseLoopsInFunctionINTEL = 5907,
DecorationBufferLocationINTEL = 5921,
DecorationIOPipeStorageINTEL = 5944,
DecorationFunctionFloatingPointModeINTEL = 6080,
DecorationSingleElementVectorINTEL = 6085,
DecorationVectorComputeCallableFunctionINTEL = 6087,
DecorationMediaBlockIOINTEL = 6140,
DecorationMax = 0x7fffffff,
};
@ -528,8 +606,10 @@ enum BuiltIn {
BuiltInBaseVertex = 4424,
BuiltInBaseInstance = 4425,
BuiltInDrawIndex = 4426,
BuiltInPrimitiveShadingRateKHR = 4432,
BuiltInDeviceIndex = 4438,
BuiltInViewIndex = 4440,
BuiltInShadingRateKHR = 4444,
BuiltInBaryCoordNoPerspAMD = 4992,
BuiltInBaryCoordNoPerspCentroidAMD = 4993,
BuiltInBaryCoordNoPerspSampleAMD = 4994,
@ -552,30 +632,48 @@ enum BuiltIn {
BuiltInLayerPerViewNV = 5279,
BuiltInMeshViewCountNV = 5280,
BuiltInMeshViewIndicesNV = 5281,
BuiltInBaryCoordKHR = 5286,
BuiltInBaryCoordNV = 5286,
BuiltInBaryCoordNoPerspKHR = 5287,
BuiltInBaryCoordNoPerspNV = 5287,
BuiltInFragSizeEXT = 5292,
BuiltInFragmentSizeNV = 5292,
BuiltInFragInvocationCountEXT = 5293,
BuiltInInvocationsPerPixelNV = 5293,
BuiltInLaunchIdKHR = 5319,
BuiltInLaunchIdNV = 5319,
BuiltInLaunchSizeKHR = 5320,
BuiltInLaunchSizeNV = 5320,
BuiltInWorldRayOriginKHR = 5321,
BuiltInWorldRayOriginNV = 5321,
BuiltInWorldRayDirectionKHR = 5322,
BuiltInWorldRayDirectionNV = 5322,
BuiltInObjectRayOriginKHR = 5323,
BuiltInObjectRayOriginNV = 5323,
BuiltInObjectRayDirectionKHR = 5324,
BuiltInObjectRayDirectionNV = 5324,
BuiltInRayTminKHR = 5325,
BuiltInRayTminNV = 5325,
BuiltInRayTmaxKHR = 5326,
BuiltInRayTmaxNV = 5326,
BuiltInInstanceCustomIndexKHR = 5327,
BuiltInInstanceCustomIndexNV = 5327,
BuiltInObjectToWorldKHR = 5330,
BuiltInObjectToWorldNV = 5330,
BuiltInWorldToObjectKHR = 5331,
BuiltInWorldToObjectNV = 5331,
BuiltInHitTNV = 5332,
BuiltInHitKindKHR = 5333,
BuiltInHitKindNV = 5333,
BuiltInCurrentRayTimeNV = 5334,
BuiltInIncomingRayFlagsKHR = 5351,
BuiltInIncomingRayFlagsNV = 5351,
BuiltInRayGeometryIndexKHR = 5352,
BuiltInWarpsPerSMNV = 5374,
BuiltInSMCountNV = 5375,
BuiltInWarpIDNV = 5376,
BuiltInSMIDNV = 5377,
BuiltInCullMaskKHR = 6021,
BuiltInMax = 0x7fffffff,
};
@ -601,6 +699,14 @@ enum LoopControlShift {
LoopControlIterationMultipleShift = 6,
LoopControlPeelCountShift = 7,
LoopControlPartialCountShift = 8,
LoopControlInitiationIntervalINTELShift = 16,
LoopControlMaxConcurrencyINTELShift = 17,
LoopControlDependencyArrayINTELShift = 18,
LoopControlPipelineEnableINTELShift = 19,
LoopControlLoopCoalesceINTELShift = 20,
LoopControlMaxInterleavingINTELShift = 21,
LoopControlSpeculatedIterationsINTELShift = 22,
LoopControlNoFusionINTELShift = 23,
LoopControlMax = 0x7fffffff,
};
@ -615,6 +721,14 @@ enum LoopControlMask {
LoopControlIterationMultipleMask = 0x00000040,
LoopControlPeelCountMask = 0x00000080,
LoopControlPartialCountMask = 0x00000100,
LoopControlInitiationIntervalINTELMask = 0x00010000,
LoopControlMaxConcurrencyINTELMask = 0x00020000,
LoopControlDependencyArrayINTELMask = 0x00040000,
LoopControlPipelineEnableINTELMask = 0x00080000,
LoopControlLoopCoalesceINTELMask = 0x00100000,
LoopControlMaxInterleavingINTELMask = 0x00200000,
LoopControlSpeculatedIterationsINTELMask = 0x00400000,
LoopControlNoFusionINTELMask = 0x00800000,
};
enum FunctionControlShift {
@ -622,6 +736,7 @@ enum FunctionControlShift {
FunctionControlDontInlineShift = 1,
FunctionControlPureShift = 2,
FunctionControlConstShift = 3,
FunctionControlOptNoneINTELShift = 16,
FunctionControlMax = 0x7fffffff,
};
@ -631,6 +746,7 @@ enum FunctionControlMask {
FunctionControlDontInlineMask = 0x00000002,
FunctionControlPureMask = 0x00000004,
FunctionControlConstMask = 0x00000008,
FunctionControlOptNoneINTELMask = 0x00010000,
};
enum MemorySemanticsShift {
@ -709,6 +825,7 @@ enum Scope {
ScopeInvocation = 4,
ScopeQueueFamily = 5,
ScopeQueueFamilyKHR = 5,
ScopeShaderCallKHR = 6,
ScopeMax = 0x7fffffff,
};
@ -810,8 +927,13 @@ enum Capability {
CapabilityGroupNonUniformQuad = 68,
CapabilityShaderLayer = 69,
CapabilityShaderViewportIndex = 70,
CapabilityUniformDecoration = 71,
CapabilityFragmentShadingRateKHR = 4422,
CapabilitySubgroupBallotKHR = 4423,
CapabilityDrawParameters = 4427,
CapabilityWorkgroupMemoryExplicitLayoutKHR = 4428,
CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR = 4429,
CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR = 4430,
CapabilitySubgroupVoteKHR = 4431,
CapabilityStorageBuffer16BitAccess = 4433,
CapabilityStorageUniformBufferBlock16 = 4433,
@ -833,11 +955,16 @@ enum Capability {
CapabilitySignedZeroInfNanPreserve = 4466,
CapabilityRoundingModeRTE = 4467,
CapabilityRoundingModeRTZ = 4468,
CapabilityRayQueryProvisionalKHR = 4471,
CapabilityRayQueryKHR = 4472,
CapabilityRayTraversalPrimitiveCullingKHR = 4478,
CapabilityRayTracingKHR = 4479,
CapabilityFloat16ImageAMD = 5008,
CapabilityImageGatherBiasLodAMD = 5009,
CapabilityFragmentMaskAMD = 5010,
CapabilityStencilExportEXT = 5013,
CapabilityImageReadWriteLodAMD = 5015,
CapabilityInt64ImageEXT = 5016,
CapabilityShaderClockKHR = 5055,
CapabilitySampleMaskOverrideCoverageNV = 5249,
CapabilityGeometryShaderPassthroughNV = 5251,
@ -849,6 +976,7 @@ enum Capability {
CapabilityFragmentFullyCoveredEXT = 5265,
CapabilityMeshShadingNV = 5266,
CapabilityImageFootprintNV = 5282,
CapabilityFragmentBarycentricKHR = 5284,
CapabilityFragmentBarycentricNV = 5284,
CapabilityComputeDerivativeGroupQuadsNV = 5288,
CapabilityFragmentDensityEXT = 5291,
@ -879,6 +1007,7 @@ enum Capability {
CapabilityStorageTexelBufferArrayNonUniformIndexing = 5312,
CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312,
CapabilityRayTracingNV = 5340,
CapabilityRayTracingMotionBlurNV = 5341,
CapabilityVulkanMemoryModel = 5345,
CapabilityVulkanMemoryModelKHR = 5345,
CapabilityVulkanMemoryModelDeviceScope = 5346,
@ -886,23 +1015,173 @@ enum Capability {
CapabilityPhysicalStorageBufferAddresses = 5347,
CapabilityPhysicalStorageBufferAddressesEXT = 5347,
CapabilityComputeDerivativeGroupLinearNV = 5350,
CapabilityRayTracingProvisionalKHR = 5353,
CapabilityCooperativeMatrixNV = 5357,
CapabilityFragmentShaderSampleInterlockEXT = 5363,
CapabilityFragmentShaderShadingRateInterlockEXT = 5372,
CapabilityShaderSMBuiltinsNV = 5373,
CapabilityFragmentShaderPixelInterlockEXT = 5378,
CapabilityDemoteToHelperInvocation = 5379,
CapabilityDemoteToHelperInvocationEXT = 5379,
CapabilityBindlessTextureNV = 5390,
CapabilitySubgroupShuffleINTEL = 5568,
CapabilitySubgroupBufferBlockIOINTEL = 5569,
CapabilitySubgroupImageBlockIOINTEL = 5570,
CapabilitySubgroupImageMediaBlockIOINTEL = 5579,
CapabilityRoundToInfinityINTEL = 5582,
CapabilityFloatingPointModeINTEL = 5583,
CapabilityIntegerFunctions2INTEL = 5584,
CapabilityFunctionPointersINTEL = 5603,
CapabilityIndirectReferencesINTEL = 5604,
CapabilityAsmINTEL = 5606,
CapabilityAtomicFloat32MinMaxEXT = 5612,
CapabilityAtomicFloat64MinMaxEXT = 5613,
CapabilityAtomicFloat16MinMaxEXT = 5616,
CapabilityVectorComputeINTEL = 5617,
CapabilityVectorAnyINTEL = 5619,
CapabilityExpectAssumeKHR = 5629,
CapabilitySubgroupAvcMotionEstimationINTEL = 5696,
CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697,
CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698,
CapabilityVariableLengthArrayINTEL = 5817,
CapabilityFunctionFloatControlINTEL = 5821,
CapabilityFPGAMemoryAttributesINTEL = 5824,
CapabilityFPFastMathModeINTEL = 5837,
CapabilityArbitraryPrecisionIntegersINTEL = 5844,
CapabilityArbitraryPrecisionFloatingPointINTEL = 5845,
CapabilityUnstructuredLoopControlsINTEL = 5886,
CapabilityFPGALoopControlsINTEL = 5888,
CapabilityKernelAttributesINTEL = 5892,
CapabilityFPGAKernelAttributesINTEL = 5897,
CapabilityFPGAMemoryAccessesINTEL = 5898,
CapabilityFPGAClusterAttributesINTEL = 5904,
CapabilityLoopFuseINTEL = 5906,
CapabilityFPGABufferLocationINTEL = 5920,
CapabilityArbitraryPrecisionFixedPointINTEL = 5922,
CapabilityUSMStorageClassesINTEL = 5935,
CapabilityIOPipesINTEL = 5943,
CapabilityBlockingPipesINTEL = 5945,
CapabilityFPGARegINTEL = 5948,
CapabilityDotProductInputAll = 6016,
CapabilityDotProductInputAllKHR = 6016,
CapabilityDotProductInput4x8Bit = 6017,
CapabilityDotProductInput4x8BitKHR = 6017,
CapabilityDotProductInput4x8BitPacked = 6018,
CapabilityDotProductInput4x8BitPackedKHR = 6018,
CapabilityDotProduct = 6019,
CapabilityDotProductKHR = 6019,
CapabilityRayCullMaskKHR = 6020,
CapabilityBitInstructions = 6025,
CapabilityAtomicFloat32AddEXT = 6033,
CapabilityAtomicFloat64AddEXT = 6034,
CapabilityLongConstantCompositeINTEL = 6089,
CapabilityOptNoneINTEL = 6094,
CapabilityAtomicFloat16AddEXT = 6095,
CapabilityDebugInfoModuleINTEL = 6114,
CapabilityMax = 0x7fffffff,
};
enum RayFlagsShift {
RayFlagsOpaqueKHRShift = 0,
RayFlagsNoOpaqueKHRShift = 1,
RayFlagsTerminateOnFirstHitKHRShift = 2,
RayFlagsSkipClosestHitShaderKHRShift = 3,
RayFlagsCullBackFacingTrianglesKHRShift = 4,
RayFlagsCullFrontFacingTrianglesKHRShift = 5,
RayFlagsCullOpaqueKHRShift = 6,
RayFlagsCullNoOpaqueKHRShift = 7,
RayFlagsSkipTrianglesKHRShift = 8,
RayFlagsSkipAABBsKHRShift = 9,
RayFlagsMax = 0x7fffffff,
};
enum RayFlagsMask {
RayFlagsMaskNone = 0,
RayFlagsOpaqueKHRMask = 0x00000001,
RayFlagsNoOpaqueKHRMask = 0x00000002,
RayFlagsTerminateOnFirstHitKHRMask = 0x00000004,
RayFlagsSkipClosestHitShaderKHRMask = 0x00000008,
RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010,
RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020,
RayFlagsCullOpaqueKHRMask = 0x00000040,
RayFlagsCullNoOpaqueKHRMask = 0x00000080,
RayFlagsSkipTrianglesKHRMask = 0x00000100,
RayFlagsSkipAABBsKHRMask = 0x00000200,
};
enum RayQueryIntersection {
RayQueryIntersectionRayQueryCandidateIntersectionKHR = 0,
RayQueryIntersectionRayQueryCommittedIntersectionKHR = 1,
RayQueryIntersectionMax = 0x7fffffff,
};
enum RayQueryCommittedIntersectionType {
RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0,
RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1,
RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2,
RayQueryCommittedIntersectionTypeMax = 0x7fffffff,
};
enum RayQueryCandidateIntersectionType {
RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0,
RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1,
RayQueryCandidateIntersectionTypeMax = 0x7fffffff,
};
enum FragmentShadingRateShift {
FragmentShadingRateVertical2PixelsShift = 0,
FragmentShadingRateVertical4PixelsShift = 1,
FragmentShadingRateHorizontal2PixelsShift = 2,
FragmentShadingRateHorizontal4PixelsShift = 3,
FragmentShadingRateMax = 0x7fffffff,
};
enum FragmentShadingRateMask {
FragmentShadingRateMaskNone = 0,
FragmentShadingRateVertical2PixelsMask = 0x00000001,
FragmentShadingRateVertical4PixelsMask = 0x00000002,
FragmentShadingRateHorizontal2PixelsMask = 0x00000004,
FragmentShadingRateHorizontal4PixelsMask = 0x00000008,
};
enum FPDenormMode {
FPDenormModePreserve = 0,
FPDenormModeFlushToZero = 1,
FPDenormModeMax = 0x7fffffff,
};
enum FPOperationMode {
FPOperationModeIEEE = 0,
FPOperationModeALT = 1,
FPOperationModeMax = 0x7fffffff,
};
enum QuantizationModes {
QuantizationModesTRN = 0,
QuantizationModesTRN_ZERO = 1,
QuantizationModesRND = 2,
QuantizationModesRND_ZERO = 3,
QuantizationModesRND_INF = 4,
QuantizationModesRND_MIN_INF = 5,
QuantizationModesRND_CONV = 6,
QuantizationModesRND_CONV_ODD = 7,
QuantizationModesMax = 0x7fffffff,
};
enum OverflowModes {
OverflowModesWRAP = 0,
OverflowModesSAT = 1,
OverflowModesSAT_ZERO = 2,
OverflowModesSAT_SYM = 3,
OverflowModesMax = 0x7fffffff,
};
enum PackedVectorFormat {
PackedVectorFormatPackedVectorFormat4x8Bit = 0,
PackedVectorFormatPackedVectorFormat4x8BitKHR = 0,
PackedVectorFormatMax = 0x7fffffff,
};
enum Op {
OpNop = 0,
OpUndef = 1,
@ -1248,12 +1527,37 @@ enum Op {
OpPtrEqual = 401,
OpPtrNotEqual = 402,
OpPtrDiff = 403,
OpTerminateInvocation = 4416,
OpSubgroupBallotKHR = 4421,
OpSubgroupFirstInvocationKHR = 4422,
OpSubgroupAllKHR = 4428,
OpSubgroupAnyKHR = 4429,
OpSubgroupAllEqualKHR = 4430,
OpSubgroupReadInvocationKHR = 4432,
OpTraceRayKHR = 4445,
OpExecuteCallableKHR = 4446,
OpConvertUToAccelerationStructureKHR = 4447,
OpIgnoreIntersectionKHR = 4448,
OpTerminateRayKHR = 4449,
OpSDot = 4450,
OpSDotKHR = 4450,
OpUDot = 4451,
OpUDotKHR = 4451,
OpSUDot = 4452,
OpSUDotKHR = 4452,
OpSDotAccSat = 4453,
OpSDotAccSatKHR = 4453,
OpUDotAccSat = 4454,
OpUDotAccSatKHR = 4454,
OpSUDotAccSat = 4455,
OpSUDotAccSatKHR = 4455,
OpTypeRayQueryKHR = 4472,
OpRayQueryInitializeKHR = 4473,
OpRayQueryTerminateKHR = 4474,
OpRayQueryGenerateIntersectionKHR = 4475,
OpRayQueryConfirmIntersectionKHR = 4476,
OpRayQueryProceedKHR = 4477,
OpRayQueryGetIntersectionTypeKHR = 4479,
OpGroupIAddNonUniformAMD = 5000,
OpGroupFAddNonUniformAMD = 5001,
OpGroupFMinNonUniformAMD = 5002,
@ -1268,10 +1572,14 @@ enum Op {
OpImageSampleFootprintNV = 5283,
OpGroupNonUniformPartitionNV = 5296,
OpWritePackedPrimitiveIndices4x8NV = 5299,
OpReportIntersectionKHR = 5334,
OpReportIntersectionNV = 5334,
OpIgnoreIntersectionNV = 5335,
OpTerminateRayNV = 5336,
OpTraceNV = 5337,
OpTraceMotionNV = 5338,
OpTraceRayMotionNV = 5339,
OpTypeAccelerationStructureKHR = 5341,
OpTypeAccelerationStructureNV = 5341,
OpExecuteCallableNV = 5344,
OpTypeCooperativeMatrixNV = 5358,
@ -1281,8 +1589,16 @@ enum Op {
OpCooperativeMatrixLengthNV = 5362,
OpBeginInvocationInterlockEXT = 5364,
OpEndInvocationInterlockEXT = 5365,
OpDemoteToHelperInvocation = 5380,
OpDemoteToHelperInvocationEXT = 5380,
OpIsHelperInvocationEXT = 5381,
OpConvertUToImageNV = 5391,
OpConvertUToSamplerNV = 5392,
OpConvertImageToUNV = 5393,
OpConvertSamplerToUNV = 5394,
OpConvertUToSampledImageNV = 5395,
OpConvertSampledImageToUNV = 5396,
OpSamplerImageAddressingModeNV = 5397,
OpSubgroupShuffleINTEL = 5571,
OpSubgroupShuffleDownINTEL = 5572,
OpSubgroupShuffleUpINTEL = 5573,
@ -1307,6 +1623,15 @@ enum Op {
OpUSubSatINTEL = 5596,
OpIMul32x16INTEL = 5597,
OpUMul32x16INTEL = 5598,
OpConstantFunctionPointerINTEL = 5600,
OpFunctionPointerCallINTEL = 5601,
OpAsmTargetINTEL = 5609,
OpAsmINTEL = 5610,
OpAsmCallINTEL = 5611,
OpAtomicFMinEXT = 5614,
OpAtomicFMaxEXT = 5615,
OpAssumeTrueKHR = 5630,
OpExpectKHR = 5631,
OpDecorateString = 5632,
OpDecorateStringGOOGLE = 5632,
OpMemberDecorateString = 5633,
@ -1429,6 +1754,89 @@ enum Op {
OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814,
OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,
OpSubgroupAvcSicGetInterRawSadsINTEL = 5816,
OpVariableLengthArrayINTEL = 5818,
OpSaveMemoryINTEL = 5819,
OpRestoreMemoryINTEL = 5820,
OpArbitraryFloatSinCosPiINTEL = 5840,
OpArbitraryFloatCastINTEL = 5841,
OpArbitraryFloatCastFromIntINTEL = 5842,
OpArbitraryFloatCastToIntINTEL = 5843,
OpArbitraryFloatAddINTEL = 5846,
OpArbitraryFloatSubINTEL = 5847,
OpArbitraryFloatMulINTEL = 5848,
OpArbitraryFloatDivINTEL = 5849,
OpArbitraryFloatGTINTEL = 5850,
OpArbitraryFloatGEINTEL = 5851,
OpArbitraryFloatLTINTEL = 5852,
OpArbitraryFloatLEINTEL = 5853,
OpArbitraryFloatEQINTEL = 5854,
OpArbitraryFloatRecipINTEL = 5855,
OpArbitraryFloatRSqrtINTEL = 5856,
OpArbitraryFloatCbrtINTEL = 5857,
OpArbitraryFloatHypotINTEL = 5858,
OpArbitraryFloatSqrtINTEL = 5859,
OpArbitraryFloatLogINTEL = 5860,
OpArbitraryFloatLog2INTEL = 5861,
OpArbitraryFloatLog10INTEL = 5862,
OpArbitraryFloatLog1pINTEL = 5863,
OpArbitraryFloatExpINTEL = 5864,
OpArbitraryFloatExp2INTEL = 5865,
OpArbitraryFloatExp10INTEL = 5866,
OpArbitraryFloatExpm1INTEL = 5867,
OpArbitraryFloatSinINTEL = 5868,
OpArbitraryFloatCosINTEL = 5869,
OpArbitraryFloatSinCosINTEL = 5870,
OpArbitraryFloatSinPiINTEL = 5871,
OpArbitraryFloatCosPiINTEL = 5872,
OpArbitraryFloatASinINTEL = 5873,
OpArbitraryFloatASinPiINTEL = 5874,
OpArbitraryFloatACosINTEL = 5875,
OpArbitraryFloatACosPiINTEL = 5876,
OpArbitraryFloatATanINTEL = 5877,
OpArbitraryFloatATanPiINTEL = 5878,
OpArbitraryFloatATan2INTEL = 5879,
OpArbitraryFloatPowINTEL = 5880,
OpArbitraryFloatPowRINTEL = 5881,
OpArbitraryFloatPowNINTEL = 5882,
OpLoopControlINTEL = 5887,
OpFixedSqrtINTEL = 5923,
OpFixedRecipINTEL = 5924,
OpFixedRsqrtINTEL = 5925,
OpFixedSinINTEL = 5926,
OpFixedCosINTEL = 5927,
OpFixedSinCosINTEL = 5928,
OpFixedSinPiINTEL = 5929,
OpFixedCosPiINTEL = 5930,
OpFixedSinCosPiINTEL = 5931,
OpFixedLogINTEL = 5932,
OpFixedExpINTEL = 5933,
OpPtrCastToCrossWorkgroupINTEL = 5934,
OpCrossWorkgroupCastToPtrINTEL = 5938,
OpReadPipeBlockingINTEL = 5946,
OpWritePipeBlockingINTEL = 5947,
OpFPGARegINTEL = 5949,
OpRayQueryGetRayTMinKHR = 6016,
OpRayQueryGetRayFlagsKHR = 6017,
OpRayQueryGetIntersectionTKHR = 6018,
OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019,
OpRayQueryGetIntersectionInstanceIdKHR = 6020,
OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021,
OpRayQueryGetIntersectionGeometryIndexKHR = 6022,
OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023,
OpRayQueryGetIntersectionBarycentricsKHR = 6024,
OpRayQueryGetIntersectionFrontFaceKHR = 6025,
OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026,
OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027,
OpRayQueryGetIntersectionObjectRayOriginKHR = 6028,
OpRayQueryGetWorldRayDirectionKHR = 6029,
OpRayQueryGetWorldRayOriginKHR = 6030,
OpRayQueryGetIntersectionObjectToWorldKHR = 6031,
OpRayQueryGetIntersectionWorldToObjectKHR = 6032,
OpAtomicFAddEXT = 6035,
OpTypeBufferSurfaceINTEL = 6086,
OpTypeStructContinuedINTEL = 6090,
OpConstantCompositeContinuedINTEL = 6091,
OpSpecConstantCompositeContinuedINTEL = 6092,
OpMax = 0x7fffffff,
};
@ -1781,12 +2189,31 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpPtrEqual: *hasResult = true; *hasResultType = true; break;
case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break;
case OpPtrDiff: *hasResult = true; *hasResultType = true; break;
case OpTerminateInvocation: *hasResult = false; *hasResultType = false; break;
case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break;
case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break;
case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break;
case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break;
case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break;
case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break;
case OpTraceRayKHR: *hasResult = false; *hasResultType = false; break;
case OpExecuteCallableKHR: *hasResult = false; *hasResultType = false; break;
case OpConvertUToAccelerationStructureKHR: *hasResult = true; *hasResultType = true; break;
case OpIgnoreIntersectionKHR: *hasResult = false; *hasResultType = false; break;
case OpTerminateRayKHR: *hasResult = false; *hasResultType = false; break;
case OpSDot: *hasResult = true; *hasResultType = true; break;
case OpUDot: *hasResult = true; *hasResultType = true; break;
case OpSUDot: *hasResult = true; *hasResultType = true; break;
case OpSDotAccSat: *hasResult = true; *hasResultType = true; break;
case OpUDotAccSat: *hasResult = true; *hasResultType = true; break;
case OpSUDotAccSat: *hasResult = true; *hasResultType = true; break;
case OpTypeRayQueryKHR: *hasResult = true; *hasResultType = false; break;
case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break;
case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break;
case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break;
case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break;
case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break;
case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break;
case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break;
case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break;
@ -1805,6 +2232,8 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break;
case OpTerminateRayNV: *hasResult = false; *hasResultType = false; break;
case OpTraceNV: *hasResult = false; *hasResultType = false; break;
case OpTraceMotionNV: *hasResult = false; *hasResultType = false; break;
case OpTraceRayMotionNV: *hasResult = false; *hasResultType = false; break;
case OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break;
case OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break;
case OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break;
@ -1814,8 +2243,15 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break;
case OpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break;
case OpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break;
case OpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break;
case OpDemoteToHelperInvocation: *hasResult = false; *hasResultType = false; break;
case OpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break;
case OpConvertUToImageNV: *hasResult = true; *hasResultType = true; break;
case OpConvertUToSamplerNV: *hasResult = true; *hasResultType = true; break;
case OpConvertImageToUNV: *hasResult = true; *hasResultType = true; break;
case OpConvertSamplerToUNV: *hasResult = true; *hasResultType = true; break;
case OpConvertUToSampledImageNV: *hasResult = true; *hasResultType = true; break;
case OpConvertSampledImageToUNV: *hasResult = true; *hasResultType = true; break;
case OpSamplerImageAddressingModeNV: *hasResult = false; *hasResultType = false; break;
case OpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break;
case OpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break;
case OpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break;
@ -1840,6 +2276,15 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break;
case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
case OpConstantFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break;
case OpFunctionPointerCallINTEL: *hasResult = true; *hasResultType = true; break;
case OpAsmTargetINTEL: *hasResult = true; *hasResultType = true; break;
case OpAsmINTEL: *hasResult = true; *hasResultType = true; break;
case OpAsmCallINTEL: *hasResult = true; *hasResultType = true; break;
case OpAtomicFMinEXT: *hasResult = true; *hasResultType = true; break;
case OpAtomicFMaxEXT: *hasResult = true; *hasResultType = true; break;
case OpAssumeTrueKHR: *hasResult = false; *hasResultType = false; break;
case OpExpectKHR: *hasResult = true; *hasResultType = true; break;
case OpDecorateString: *hasResult = false; *hasResultType = false; break;
case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break;
case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break;
@ -1960,6 +2405,89 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break;
case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break;
case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break;
case OpVariableLengthArrayINTEL: *hasResult = true; *hasResultType = true; break;
case OpSaveMemoryINTEL: *hasResult = true; *hasResultType = true; break;
case OpRestoreMemoryINTEL: *hasResult = false; *hasResultType = false; break;
case OpArbitraryFloatSinCosPiINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatCastINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatCastFromIntINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatCastToIntINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatAddINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatSubINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatMulINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatDivINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatGTINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatGEINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatLTINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatLEINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatEQINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatRecipINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatRSqrtINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatCbrtINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatHypotINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatSqrtINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatLogINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatLog2INTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatLog10INTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatLog1pINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatExpINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatExp2INTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatExp10INTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatExpm1INTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatSinINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatCosINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatSinCosINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatSinPiINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatCosPiINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatASinINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatASinPiINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatACosINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatACosPiINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatATanINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatATanPiINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatATan2INTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatPowINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatPowRINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatPowNINTEL: *hasResult = true; *hasResultType = true; break;
case OpLoopControlINTEL: *hasResult = false; *hasResultType = false; break;
case OpFixedSqrtINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedRecipINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedRsqrtINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedSinINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedCosINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedSinCosINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedSinPiINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedCosPiINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedSinCosPiINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedLogINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedExpINTEL: *hasResult = true; *hasResultType = true; break;
case OpPtrCastToCrossWorkgroupINTEL: *hasResult = true; *hasResultType = true; break;
case OpCrossWorkgroupCastToPtrINTEL: *hasResult = true; *hasResultType = true; break;
case OpReadPipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
case OpWritePipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
case OpFPGARegINTEL: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break;
case OpAtomicFAddEXT: *hasResult = true; *hasResultType = true; break;
case OpTypeBufferSurfaceINTEL: *hasResult = true; *hasResultType = false; break;
case OpTypeStructContinuedINTEL: *hasResult = false; *hasResultType = false; break;
case OpConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break;
case OpSpecConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break;
}
}
#endif /* SPV_ENABLE_UTILITY_CODE */
@ -1974,6 +2502,8 @@ inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask
inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); }
inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); }
inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); }
inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); }
inline FragmentShadingRateMask operator|(FragmentShadingRateMask a, FragmentShadingRateMask b) { return FragmentShadingRateMask(unsigned(a) | unsigned(b)); }
} // end namespace spv

View file

@ -55,6 +55,7 @@
#include <iostream>
#include <memory>
#include <vector>
#include <set>
namespace spv {
@ -110,27 +111,23 @@ public:
void addStringOperand(const char* str)
{
unsigned int word;
char* wordString = (char*)&word;
char* wordPtr = wordString;
int charCount = 0;
unsigned int word = 0;
unsigned int shiftAmount = 0;
char c;
do {
c = *(str++);
*(wordPtr++) = c;
++charCount;
if (charCount == 4) {
word |= ((unsigned int)c) << shiftAmount;
shiftAmount += 8;
if (shiftAmount == 32) {
addImmediateOperand(word);
wordPtr = wordString;
charCount = 0;
word = 0;
shiftAmount = 0;
}
} while (c != 0);
// deal with partial last word
if (charCount > 0) {
// pad with 0s
for (; charCount < 4; ++charCount)
*(wordPtr++) = 0;
if (shiftAmount > 0) {
addImmediateOperand(word);
}
}
@ -235,8 +232,7 @@ public:
assert(instructions.size() > 0);
instructions.resize(1);
successors.clear();
Instruction* unreachable = new Instruction(OpUnreachable);
addInstruction(std::unique_ptr<Instruction>(unreachable));
addInstruction(std::unique_ptr<Instruction>(new Instruction(OpUnreachable)));
}
// Change this block into a canonical dead continue target branching to the
// given header ID. Delete instructions as necessary. A canonical dead continue
@ -263,6 +259,7 @@ public:
case OpBranchConditional:
case OpSwitch:
case OpKill:
case OpTerminateInvocation:
case OpReturn:
case OpReturnValue:
case OpUnreachable:
@ -352,12 +349,43 @@ public:
const std::vector<Block*>& getBlocks() const { return blocks; }
void addLocalVariable(std::unique_ptr<Instruction> inst);
Id getReturnType() const { return functionInstruction.getTypeId(); }
void setReturnPrecision(Decoration precision)
{
if (precision == DecorationRelaxedPrecision)
reducedPrecisionReturn = true;
}
Decoration getReturnPrecision() const
{ return reducedPrecisionReturn ? DecorationRelaxedPrecision : NoPrecision; }
void setDebugLineInfo(Id fileName, int line, int column) {
lineInstruction = std::unique_ptr<Instruction>{new Instruction(OpLine)};
lineInstruction->addIdOperand(fileName);
lineInstruction->addImmediateOperand(line);
lineInstruction->addImmediateOperand(column);
}
bool hasDebugLineInfo() const { return lineInstruction != nullptr; }
void setImplicitThis() { implicitThis = true; }
bool hasImplicitThis() const { return implicitThis; }
void addParamPrecision(unsigned param, Decoration precision)
{
if (precision == DecorationRelaxedPrecision)
reducedPrecisionParams.insert(param);
}
Decoration getParamPrecision(unsigned param) const
{
return reducedPrecisionParams.find(param) != reducedPrecisionParams.end() ?
DecorationRelaxedPrecision : NoPrecision;
}
void dump(std::vector<unsigned int>& out) const
{
// OpLine
if (lineInstruction != nullptr) {
lineInstruction->dump(out);
}
// OpFunction
functionInstruction.dump(out);
@ -376,10 +404,13 @@ protected:
Function& operator=(Function&);
Module& parent;
std::unique_ptr<Instruction> lineInstruction;
Instruction functionInstruction;
std::vector<Instruction*> parameterInstructions;
std::vector<Block*> blocks;
bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument
bool reducedPrecisionReturn;
std::set<int> reducedPrecisionParams; // list of parameter indexes that need a relaxed precision arg
};
//
@ -440,7 +471,9 @@ protected:
// - the OpFunction instruction
// - all the OpFunctionParameter instructions
__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent)
: parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false)
: parent(parent), lineInstruction(nullptr),
functionInstruction(id, resultType, OpFunction), implicitThis(false),
reducedPrecisionReturn(false)
{
// OpFunction
functionInstruction.addImmediateOperand(FunctionControlMaskNone);

View file

@ -958,16 +958,24 @@ set (VULKAN_SOURCES
common/rendering/vulkan/system/vk_swapchain.cpp
common/rendering/vulkan/system/vk_builders.cpp
common/rendering/vulkan/system/vk_framebuffer.cpp
common/rendering/vulkan/system/vk_buffers.cpp
common/rendering/vulkan/system/vk_commandbuffer.cpp
common/rendering/vulkan/system/vk_hwbuffer.cpp
common/rendering/vulkan/system/vk_buffer.cpp
common/rendering/vulkan/renderer/vk_renderstate.cpp
common/rendering/vulkan/renderer/vk_renderpass.cpp
common/rendering/vulkan/renderer/vk_streambuffer.cpp
common/rendering/vulkan/renderer/vk_postprocess.cpp
common/rendering/vulkan/renderer/vk_renderbuffers.cpp
common/rendering/vulkan/renderer/vk_pprenderstate.cpp
common/rendering/vulkan/renderer/vk_descriptorset.cpp
common/rendering/vulkan/renderer/vk_raytrace.cpp
common/rendering/vulkan/shaders/vk_shader.cpp
common/rendering/vulkan/shaders/vk_ppshader.cpp
common/rendering/vulkan/textures/vk_samplers.cpp
common/rendering/vulkan/textures/vk_hwtexture.cpp
common/rendering/vulkan/textures/vk_pptexture.cpp
common/rendering/vulkan/textures/vk_imagetransition.cpp
common/rendering/vulkan/textures/vk_renderbuffers.cpp
common/rendering/vulkan/textures/vk_texture.cpp
common/rendering/vulkan/thirdparty/volk/volk.c
common/rendering/vulkan/thirdparty/vk_mem_alloc/vk_mem_alloc.cpp
)

View file

@ -0,0 +1,21 @@
#pragma once
#include "tarray.h"
#include "vectors.h"
namespace hwrenderer
{
class LevelMesh
{
public:
virtual ~LevelMesh() = default;
TArray<FVector3> MeshVertices;
TArray<int> MeshUVIndex;
TArray<uint32_t> MeshElements;
TArray<int> MeshSurfaces;
};
} // namespace

View file

@ -43,6 +43,7 @@
#include "v_2ddrawer.h"
#include "intrect.h"
#include "hw_shadowmap.h"
#include "hw_levelmesh.h"
#include "buffers.h"
@ -164,6 +165,7 @@ public:
{
mShadowMap.SetAABBTree(tree);
}
virtual void SetLevelMesh(hwrenderer::LevelMesh *mesh) { }
bool allowSSBO()
{
#ifndef HW_BLOCK_SSBO

View file

@ -0,0 +1,289 @@
/*
** Vulkan backend
** Copyright (c) 2016-2020 Magnus Norddahl
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
**
*/
#include "vk_descriptorset.h"
#include "vk_streambuffer.h"
#include "vk_raytrace.h"
#include "vulkan/shaders/vk_shader.h"
#include "vulkan/textures/vk_samplers.h"
#include "vulkan/textures/vk_renderbuffers.h"
#include "vulkan/textures/vk_hwtexture.h"
#include "vulkan/textures/vk_texture.h"
#include "vulkan/system/vk_builders.h"
#include "vulkan/system/vk_framebuffer.h"
#include "vulkan/system/vk_hwbuffer.h"
#include "vulkan/system/vk_commandbuffer.h"
#include "vulkan/system/vk_buffer.h"
#include "flatvertices.h"
#include "hw_viewpointuniforms.h"
#include "v_2ddrawer.h"
VkDescriptorSetManager::VkDescriptorSetManager(VulkanFrameBuffer* fb) : fb(fb)
{
CreateHWBufferSetLayout();
CreateFixedSetLayout();
CreateHWBufferPool();
CreateFixedSetPool();
}
VkDescriptorSetManager::~VkDescriptorSetManager()
{
while (!Materials.empty())
RemoveMaterial(Materials.back());
}
void VkDescriptorSetManager::Init()
{
UpdateFixedSet();
UpdateHWBufferSet();
}
void VkDescriptorSetManager::Deinit()
{
while (!Materials.empty())
RemoveMaterial(Materials.back());
}
void VkDescriptorSetManager::BeginFrame()
{
UpdateFixedSet();
UpdateHWBufferSet();
}
void VkDescriptorSetManager::UpdateHWBufferSet()
{
fb->GetCommands()->DrawDeleteList->Add(std::move(HWBufferSet));
HWBufferSet = HWBufferDescriptorPool->tryAllocate(HWBufferSetLayout.get());
if (!HWBufferSet)
{
fb->GetCommands()->WaitForCommands(false);
HWBufferSet = HWBufferDescriptorPool->allocate(HWBufferSetLayout.get());
}
WriteDescriptors()
.AddBuffer(HWBufferSet.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->GetBufferManager()->ViewpointUBO->mBuffer.get(), 0, sizeof(HWViewpointUniforms))
.AddBuffer(HWBufferSet.get(), 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->GetBufferManager()->MatrixBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(MatricesUBO))
.AddBuffer(HWBufferSet.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->GetBufferManager()->StreamBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(StreamUBO))
.AddBuffer(HWBufferSet.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightBufferSSO->mBuffer.get())
.Execute(fb->device);
}
void VkDescriptorSetManager::UpdateFixedSet()
{
fb->GetCommands()->DrawDeleteList->Add(std::move(FixedSet));
FixedSet = FixedDescriptorPool->tryAllocate(FixedSetLayout.get());
if (!FixedSet)
{
fb->GetCommands()->WaitForCommands(false);
FixedSet = FixedDescriptorPool->allocate(FixedSetLayout.get());
}
WriteDescriptors update;
update.AddCombinedImageSampler(FixedSet.get(), 0, fb->GetTextureManager()->Shadowmap.View.get(), fb->GetSamplerManager()->ShadowmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
update.AddCombinedImageSampler(FixedSet.get(), 1, fb->GetTextureManager()->Lightmap.View.get(), fb->GetSamplerManager()->LightmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
if (fb->RaytracingEnabled())
update.AddAccelerationStructure(FixedSet.get(), 2, fb->GetRaytrace()->GetAccelStruct());
update.Execute(fb->device);
}
void VkDescriptorSetManager::ResetHWTextureSets()
{
for (auto mat : Materials)
mat->DeleteDescriptors();
auto deleteList = fb->GetCommands()->DrawDeleteList.get();
for (auto& desc : TextureDescriptorPools)
{
deleteList->Add(std::move(desc));
}
deleteList->Add(std::move(NullTextureDescriptorSet));
TextureDescriptorPools.clear();
TextureDescriptorSetsLeft = 0;
TextureDescriptorsLeft = 0;
}
VulkanDescriptorSet* VkDescriptorSetManager::GetNullTextureDescriptorSet()
{
if (!NullTextureDescriptorSet)
{
NullTextureDescriptorSet = AllocateTextureDescriptorSet(SHADER_MIN_REQUIRED_TEXTURE_LAYERS);
WriteDescriptors update;
for (int i = 0; i < SHADER_MIN_REQUIRED_TEXTURE_LAYERS; i++)
{
update.AddCombinedImageSampler(NullTextureDescriptorSet.get(), i, fb->GetTextureManager()->GetNullTextureView(), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
update.Execute(fb->device);
}
return NullTextureDescriptorSet.get();
}
std::unique_ptr<VulkanDescriptorSet> VkDescriptorSetManager::AllocateTextureDescriptorSet(int numLayers)
{
if (TextureDescriptorSetsLeft == 0 || TextureDescriptorsLeft < numLayers)
{
TextureDescriptorSetsLeft = 1000;
TextureDescriptorsLeft = 2000;
TextureDescriptorPools.push_back(DescriptorPoolBuilder()
.AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, TextureDescriptorsLeft)
.MaxSets(TextureDescriptorSetsLeft)
.DebugName("VkDescriptorSetManager.TextureDescriptorPool")
.Create(fb->device));
}
TextureDescriptorSetsLeft--;
TextureDescriptorsLeft -= numLayers;
return TextureDescriptorPools.back()->allocate(GetTextureSetLayout(numLayers));
}
VulkanDescriptorSetLayout* VkDescriptorSetManager::GetTextureSetLayout(int numLayers)
{
if (TextureSetLayouts.size() < (size_t)numLayers)
TextureSetLayouts.resize(numLayers);
auto& layout = TextureSetLayouts[numLayers - 1];
if (layout)
return layout.get();
DescriptorSetLayoutBuilder builder;
for (int i = 0; i < numLayers; i++)
{
builder.AddBinding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
}
builder.DebugName("VkDescriptorSetManager.TextureSetLayout");
layout = builder.Create(fb->device);
return layout.get();
}
void VkDescriptorSetManager::AddMaterial(VkMaterial* texture)
{
texture->it = Materials.insert(Materials.end(), texture);
}
void VkDescriptorSetManager::RemoveMaterial(VkMaterial* texture)
{
texture->DeleteDescriptors();
texture->fb = nullptr;
Materials.erase(texture->it);
}
VulkanDescriptorSet* VkDescriptorSetManager::GetInput(VkPPRenderPassSetup* passSetup, const TArray<PPTextureInput>& textures, bool bindShadowMapBuffers)
{
auto descriptors = AllocatePPDescriptorSet(passSetup->DescriptorLayout.get());
descriptors->SetDebugName("VkPostprocess.descriptors");
WriteDescriptors write;
VkImageTransition imageTransition;
for (unsigned int index = 0; index < textures.Size(); index++)
{
const PPTextureInput& input = textures[index];
VulkanSampler* sampler = fb->GetSamplerManager()->Get(input.Filter, input.Wrap);
VkTextureImage* tex = fb->GetTextureManager()->GetTexture(input.Type, input.Texture);
write.AddCombinedImageSampler(descriptors.get(), index, tex->DepthOnlyView ? tex->DepthOnlyView.get() : tex->View.get(), sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
imageTransition.AddImage(tex, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
}
if (bindShadowMapBuffers)
{
write.AddBuffer(descriptors.get(), LIGHTNODES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightNodes->mBuffer.get());
write.AddBuffer(descriptors.get(), LIGHTLINES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightLines->mBuffer.get());
write.AddBuffer(descriptors.get(), LIGHTLIST_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightList->mBuffer.get());
}
write.Execute(fb->device);
imageTransition.Execute(fb->GetCommands()->GetDrawCommands());
VulkanDescriptorSet* set = descriptors.get();
fb->GetCommands()->DrawDeleteList->Add(std::move(descriptors));
return set;
}
std::unique_ptr<VulkanDescriptorSet> VkDescriptorSetManager::AllocatePPDescriptorSet(VulkanDescriptorSetLayout* layout)
{
if (PPDescriptorPool)
{
auto descriptors = PPDescriptorPool->tryAllocate(layout);
if (descriptors)
return descriptors;
fb->GetCommands()->DrawDeleteList->Add(std::move(PPDescriptorPool));
}
PPDescriptorPool = DescriptorPoolBuilder()
.AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 200)
.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4)
.MaxSets(100)
.DebugName("PPDescriptorPool")
.Create(fb->device);
return PPDescriptorPool->allocate(layout);
}
void VkDescriptorSetManager::CreateHWBufferSetLayout()
{
HWBufferSetLayout = DescriptorSetLayoutBuilder()
.AddBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
.AddBinding(1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
.AddBinding(2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
.AddBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
.DebugName("VkDescriptorSetManager.HWBufferSetLayout")
.Create(fb->device);
}
void VkDescriptorSetManager::CreateFixedSetLayout()
{
DescriptorSetLayoutBuilder builder;
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
builder.AddBinding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
if (fb->RaytracingEnabled())
builder.AddBinding(2, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
builder.DebugName("VkDescriptorSetManager.FixedSetLayout");
FixedSetLayout = builder.Create(fb->device);
}
void VkDescriptorSetManager::CreateHWBufferPool()
{
HWBufferDescriptorPool = DescriptorPoolBuilder()
.AddPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 3 * maxSets)
.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1 * maxSets)
.MaxSets(maxSets)
.DebugName("VkDescriptorSetManager.HWBufferDescriptorPool")
.Create(fb->device);
}
void VkDescriptorSetManager::CreateFixedSetPool()
{
DescriptorPoolBuilder poolbuilder;
poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2 * maxSets);
if (fb->RaytracingEnabled())
poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 * maxSets);
poolbuilder.MaxSets(maxSets);
poolbuilder.DebugName("VkDescriptorSetManager.FixedDescriptorPool");
FixedDescriptorPool = poolbuilder.Create(fb->device);
}

View file

@ -0,0 +1,70 @@
#pragma once
#include "vulkan/system/vk_objects.h"
#include <list>
class VulkanFrameBuffer;
class VkMaterial;
class PPTextureInput;
class VkPPRenderPassSetup;
class VkDescriptorSetManager
{
public:
VkDescriptorSetManager(VulkanFrameBuffer* fb);
~VkDescriptorSetManager();
void Init();
void Deinit();
void BeginFrame();
void UpdateFixedSet();
void UpdateHWBufferSet();
void ResetHWTextureSets();
VulkanDescriptorSetLayout* GetHWBufferSetLayout() { return HWBufferSetLayout.get(); }
VulkanDescriptorSetLayout* GetFixedSetLayout() { return FixedSetLayout.get(); }
VulkanDescriptorSetLayout* GetTextureSetLayout(int numLayers);
VulkanDescriptorSet* GetHWBufferDescriptorSet() { return HWBufferSet.get(); }
VulkanDescriptorSet* GetFixedDescriptorSet() { return FixedSet.get(); }
VulkanDescriptorSet* GetNullTextureDescriptorSet();
std::unique_ptr<VulkanDescriptorSet> AllocateTextureDescriptorSet(int numLayers);
VulkanDescriptorSet* GetInput(VkPPRenderPassSetup* passSetup, const TArray<PPTextureInput>& textures, bool bindShadowMapBuffers);
void AddMaterial(VkMaterial* texture);
void RemoveMaterial(VkMaterial* texture);
private:
void CreateHWBufferSetLayout();
void CreateFixedSetLayout();
void CreateHWBufferPool();
void CreateFixedSetPool();
std::unique_ptr<VulkanDescriptorSet> AllocatePPDescriptorSet(VulkanDescriptorSetLayout* layout);
VulkanFrameBuffer* fb = nullptr;
std::unique_ptr<VulkanDescriptorSetLayout> HWBufferSetLayout;
std::unique_ptr<VulkanDescriptorSetLayout> FixedSetLayout;
std::vector<std::unique_ptr<VulkanDescriptorSetLayout>> TextureSetLayouts;
std::unique_ptr<VulkanDescriptorPool> HWBufferDescriptorPool;
std::unique_ptr<VulkanDescriptorPool> FixedDescriptorPool;
std::unique_ptr<VulkanDescriptorPool> PPDescriptorPool;
int TextureDescriptorSetsLeft = 0;
int TextureDescriptorsLeft = 0;
std::vector<std::unique_ptr<VulkanDescriptorPool>> TextureDescriptorPools;
std::unique_ptr<VulkanDescriptorSet> HWBufferSet;
std::unique_ptr<VulkanDescriptorSet> FixedSet;
std::unique_ptr<VulkanDescriptorSet> NullTextureDescriptorSet;
std::list<VkMaterial*> Materials;
static const int maxSets = 10;
};

View file

@ -21,26 +21,29 @@
*/
#include "vk_postprocess.h"
#include "vk_renderbuffers.h"
#include "vulkan/shaders/vk_shader.h"
#include "vulkan/system/vk_builders.h"
#include "vulkan/system/vk_framebuffer.h"
#include "vulkan/system/vk_buffers.h"
#include "vulkan/system/vk_hwbuffer.h"
#include "vulkan/system/vk_swapchain.h"
#include "vulkan/system/vk_commandbuffer.h"
#include "vulkan/renderer/vk_renderstate.h"
#include "vulkan/renderer/vk_pprenderstate.h"
#include "vulkan/shaders/vk_ppshader.h"
#include "vulkan/textures/vk_pptexture.h"
#include "vulkan/textures/vk_renderbuffers.h"
#include "vulkan/textures/vk_imagetransition.h"
#include "vulkan/textures/vk_texture.h"
#include "hw_cvars.h"
#include "hwrenderer/postprocessing/hw_postprocess.h"
#include "hwrenderer/postprocessing/hw_postprocess_cvars.h"
#include "hw_vrmodes.h"
#include "flatvertices.h"
#include "r_videoscale.h"
#include "filesystem.h"
EXTERN_CVAR(Int, gl_dither_bpc)
VkPostprocess::VkPostprocess()
VkPostprocess::VkPostprocess(VulkanFrameBuffer* fb) : fb(fb)
{
}
@ -50,23 +53,21 @@ VkPostprocess::~VkPostprocess()
void VkPostprocess::SetActiveRenderTarget()
{
auto fb = GetVulkanFrameBuffer();
auto buffers = fb->GetBuffers();
VkImageTransition imageTransition;
imageTransition.addImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false);
imageTransition.execute(fb->GetDrawCommands());
VkImageTransition()
.AddImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false)
.Execute(fb->GetCommands()->GetDrawCommands());
fb->GetRenderState()->SetRenderTarget(&buffers->PipelineImage[mCurrentPipelineImage], nullptr, buffers->GetWidth(), buffers->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, VK_SAMPLE_COUNT_1_BIT);
}
void VkPostprocess::PostProcessScene(int fixedcm, float flash, const std::function<void()> &afterBloomDrawEndScene2D)
{
auto fb = GetVulkanFrameBuffer();
int sceneWidth = fb->GetBuffers()->GetSceneWidth();
int sceneHeight = fb->GetBuffers()->GetSceneHeight();
VkPPRenderState renderstate;
VkPPRenderState renderstate(fb);
hw_postprocess.Pass1(&renderstate, fixedcm, sceneWidth, sceneHeight);
SetActiveRenderTarget();
@ -76,19 +77,17 @@ void VkPostprocess::PostProcessScene(int fixedcm, float flash, const std::functi
void VkPostprocess::BlitSceneToPostprocess()
{
auto fb = GetVulkanFrameBuffer();
fb->GetRenderState()->EndRenderPass();
auto buffers = fb->GetBuffers();
auto cmdbuffer = fb->GetDrawCommands();
auto cmdbuffer = fb->GetCommands()->GetDrawCommands();
mCurrentPipelineImage = 0;
VkImageTransition imageTransition;
imageTransition.addImage(&buffers->SceneColor, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false);
imageTransition.addImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
imageTransition.execute(fb->GetDrawCommands());
VkImageTransition()
.AddImage(&buffers->SceneColor, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false)
.AddImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true)
.Execute(fb->GetCommands()->GetDrawCommands());
if (buffers->GetSceneSamples() != VK_SAMPLE_COUNT_1_BIT)
{
@ -135,30 +134,27 @@ void VkPostprocess::BlitSceneToPostprocess()
void VkPostprocess::ImageTransitionScene(bool undefinedSrcLayout)
{
auto fb = GetVulkanFrameBuffer();
auto buffers = fb->GetBuffers();
VkImageTransition imageTransition;
imageTransition.addImage(&buffers->SceneColor, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout);
imageTransition.addImage(&buffers->SceneFog, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout);
imageTransition.addImage(&buffers->SceneNormal, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout);
imageTransition.addImage(&buffers->SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, undefinedSrcLayout);
imageTransition.execute(fb->GetDrawCommands());
VkImageTransition()
.AddImage(&buffers->SceneColor, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout)
.AddImage(&buffers->SceneFog, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout)
.AddImage(&buffers->SceneNormal, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout)
.AddImage(&buffers->SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, undefinedSrcLayout)
.Execute(fb->GetCommands()->GetDrawCommands());
}
void VkPostprocess::BlitCurrentToImage(VkTextureImage *dstimage, VkImageLayout finallayout)
{
auto fb = GetVulkanFrameBuffer();
fb->GetRenderState()->EndRenderPass();
auto srcimage = &fb->GetBuffers()->PipelineImage[mCurrentPipelineImage];
auto cmdbuffer = fb->GetDrawCommands();
auto cmdbuffer = fb->GetCommands()->GetDrawCommands();
VkImageTransition imageTransition0;
imageTransition0.addImage(srcimage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false);
imageTransition0.addImage(dstimage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
imageTransition0.execute(cmdbuffer);
VkImageTransition()
.AddImage(srcimage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false)
.AddImage(dstimage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true)
.Execute(cmdbuffer);
VkImageBlit blit = {};
blit.srcOffsets[0] = { 0, 0, 0 };
@ -173,21 +169,20 @@ void VkPostprocess::BlitCurrentToImage(VkTextureImage *dstimage, VkImageLayout f
blit.dstSubresource.mipLevel = 0;
blit.dstSubresource.baseArrayLayer = 0;
blit.dstSubresource.layerCount = 1;
cmdbuffer->blitImage(
srcimage->Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
dstimage->Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &blit, VK_FILTER_NEAREST);
VkImageTransition imageTransition1;
imageTransition1.addImage(dstimage, finallayout, false);
imageTransition1.execute(cmdbuffer);
VkImageTransition()
.AddImage(dstimage, finallayout, false)
.Execute(cmdbuffer);
}
void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool screenshot)
{
auto fb = GetVulkanFrameBuffer();
VkPPRenderState renderstate;
VkPPRenderState renderstate(fb);
if (!screenshot) // Already applied as we are actually copying the last frame here (GetScreenshotBuffer is called after swap)
hw_postprocess.customShaders.Run(&renderstate, "screen");
@ -221,7 +216,7 @@ void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool
uniforms.Offset = { 0.0f, 1.0f };
}
if (applyGamma && fb->swapChain->IsHdrModeActive() && !screenshot)
if (applyGamma && fb->GetCommands()->swapChain->IsHdrModeActive() && !screenshot)
{
uniforms.HdrMode = 1;
}
@ -246,11 +241,10 @@ void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool
void VkPostprocess::AmbientOccludeScene(float m5)
{
auto fb = GetVulkanFrameBuffer();
int sceneWidth = fb->GetBuffers()->GetSceneWidth();
int sceneHeight = fb->GetBuffers()->GetSceneHeight();
VkPPRenderState renderstate;
VkPPRenderState renderstate(fb);
hw_postprocess.ssao.Render(&renderstate, m5, sceneWidth, sceneHeight);
ImageTransitionScene(false);
@ -258,11 +252,10 @@ void VkPostprocess::AmbientOccludeScene(float m5)
void VkPostprocess::BlurScene(float gameinfobluramount)
{
auto fb = GetVulkanFrameBuffer();
int sceneWidth = fb->GetBuffers()->GetSceneWidth();
int sceneHeight = fb->GetBuffers()->GetSceneHeight();
VkPPRenderState renderstate;
VkPPRenderState renderstate(fb);
auto vrmode = VRMode::GetVRMode(true);
int eyeCount = vrmode->mEyeCount;
@ -282,537 +275,17 @@ void VkPostprocess::UpdateShadowMap()
{
if (screen->mShadowMap.PerformUpdate())
{
VkPPRenderState renderstate;
VkPPRenderState renderstate(fb);
hw_postprocess.shadowmap.Update(&renderstate);
auto fb = GetVulkanFrameBuffer();
auto buffers = fb->GetBuffers();
VkImageTransition imageTransition;
imageTransition.addImage(&buffers->Shadowmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
imageTransition.execute(fb->GetDrawCommands());
VkImageTransition()
.AddImage(&fb->GetTextureManager()->Shadowmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false)
.Execute(fb->GetCommands()->GetDrawCommands());
screen->mShadowMap.FinishUpdate();
}
}
std::unique_ptr<VulkanDescriptorSet> VkPostprocess::AllocateDescriptorSet(VulkanDescriptorSetLayout *layout)
{
if (mDescriptorPool)
{
auto descriptors = mDescriptorPool->tryAllocate(layout);
if (descriptors)
return descriptors;
GetVulkanFrameBuffer()->FrameDeleteList.DescriptorPools.push_back(std::move(mDescriptorPool));
}
DescriptorPoolBuilder builder;
builder.addPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 200);
builder.addPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4);
builder.setMaxSets(100);
mDescriptorPool = builder.create(GetVulkanFrameBuffer()->device);
mDescriptorPool->SetDebugName("VkPostprocess.mDescriptorPool");
return mDescriptorPool->allocate(layout);
}
void VkPostprocess::RenderBuffersReset()
{
mRenderPassSetup.clear();
}
VulkanSampler *VkPostprocess::GetSampler(PPFilterMode filter, PPWrapMode wrap)
{
int index = (((int)filter) << 1) | (int)wrap;
auto &sampler = mSamplers[index];
if (sampler)
return sampler.get();
SamplerBuilder builder;
builder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST);
builder.setMinFilter(filter == PPFilterMode::Nearest ? VK_FILTER_NEAREST : VK_FILTER_LINEAR);
builder.setMagFilter(filter == PPFilterMode::Nearest ? VK_FILTER_NEAREST : VK_FILTER_LINEAR);
builder.setAddressMode(wrap == PPWrapMode::Clamp ? VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : VK_SAMPLER_ADDRESS_MODE_REPEAT);
sampler = builder.create(GetVulkanFrameBuffer()->device);
sampler->SetDebugName("VkPostprocess.mSamplers");
return sampler.get();
}
void VkPostprocess::NextEye(int eyeCount)
{
}
/////////////////////////////////////////////////////////////////////////////
VkPPTexture::VkPPTexture(PPTexture *texture)
{
auto fb = GetVulkanFrameBuffer();
VkFormat format;
int pixelsize;
switch (texture->Format)
{
default:
case PixelFormat::Rgba8: format = VK_FORMAT_R8G8B8A8_UNORM; pixelsize = 4; break;
case PixelFormat::Rgba16f: format = VK_FORMAT_R16G16B16A16_SFLOAT; pixelsize = 8; break;
case PixelFormat::R32f: format = VK_FORMAT_R32_SFLOAT; pixelsize = 4; break;
case PixelFormat::Rg16f: format = VK_FORMAT_R16G16_SFLOAT; pixelsize = 4; break;
case PixelFormat::Rgba16_snorm: format = VK_FORMAT_R16G16B16A16_SNORM; pixelsize = 8; break;
}
ImageBuilder imgbuilder;
imgbuilder.setFormat(format);
imgbuilder.setSize(texture->Width, texture->Height);
if (texture->Data)
imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
else
imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
if (!imgbuilder.isFormatSupported(fb->device))
I_FatalError("Vulkan device does not support the image format required by a postprocess texture\n");
TexImage.Image = imgbuilder.create(fb->device);
TexImage.Image->SetDebugName("VkPPTexture");
Format = format;
ImageViewBuilder viewbuilder;
viewbuilder.setImage(TexImage.Image.get(), format);
TexImage.View = viewbuilder.create(fb->device);
TexImage.View->SetDebugName("VkPPTextureView");
if (texture->Data)
{
size_t totalsize = texture->Width * texture->Height * pixelsize;
BufferBuilder stagingbuilder;
stagingbuilder.setSize(totalsize);
stagingbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
Staging = stagingbuilder.create(fb->device);
Staging->SetDebugName("VkPPTextureStaging");
VkImageTransition barrier0;
barrier0.addImage(&TexImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
barrier0.execute(fb->GetTransferCommands());
void *data = Staging->Map(0, totalsize);
memcpy(data, texture->Data.get(), totalsize);
Staging->Unmap();
VkBufferImageCopy region = {};
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.layerCount = 1;
region.imageExtent.depth = 1;
region.imageExtent.width = texture->Width;
region.imageExtent.height = texture->Height;
fb->GetTransferCommands()->copyBufferToImage(Staging->buffer, TexImage.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
VkImageTransition barrier1;
barrier1.addImage(&TexImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
barrier1.execute(fb->GetTransferCommands());
}
else
{
VkImageTransition barrier;
barrier.addImage(&TexImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
barrier.execute(fb->GetTransferCommands());
}
}
VkPPTexture::~VkPPTexture()
{
if (auto fb = GetVulkanFrameBuffer())
{
if (TexImage.Image) fb->FrameDeleteList.Images.push_back(std::move(TexImage.Image));
if (TexImage.View) fb->FrameDeleteList.ImageViews.push_back(std::move(TexImage.View));
if (TexImage.DepthOnlyView) fb->FrameDeleteList.ImageViews.push_back(std::move(TexImage.DepthOnlyView));
if (TexImage.PPFramebuffer) fb->FrameDeleteList.Framebuffers.push_back(std::move(TexImage.PPFramebuffer));
if (Staging) fb->FrameDeleteList.Buffers.push_back(std::move(Staging));
}
}
/////////////////////////////////////////////////////////////////////////////
VkPPShader::VkPPShader(PPShader *shader)
{
auto fb = GetVulkanFrameBuffer();
FString prolog;
if (!shader->Uniforms.empty())
prolog = UniformBlockDecl::Create("Uniforms", shader->Uniforms, -1);
prolog += shader->Defines;
ShaderBuilder vertbuilder;
vertbuilder.setVertexShader(LoadShaderCode(shader->VertexShader, "", shader->Version));
VertexShader = vertbuilder.create(shader->VertexShader.GetChars(), fb->device);
VertexShader->SetDebugName(shader->VertexShader.GetChars());
ShaderBuilder fragbuilder;
fragbuilder.setFragmentShader(LoadShaderCode(shader->FragmentShader, prolog, shader->Version));
FragmentShader = fragbuilder.create(shader->FragmentShader.GetChars(), fb->device);
FragmentShader->SetDebugName(shader->FragmentShader.GetChars());
}
FString VkPPShader::LoadShaderCode(const FString &lumpName, const FString &defines, int version)
{
int lump = fileSystem.CheckNumForFullName(lumpName);
if (lump == -1) I_FatalError("Unable to load '%s'", lumpName.GetChars());
FString code = fileSystem.ReadFile(lump).GetString().GetChars();
FString patchedCode;
patchedCode.AppendFormat("#version %d\n", 450);
patchedCode << defines;
patchedCode << "#line 1\n";
patchedCode << code;
return patchedCode;
}
/////////////////////////////////////////////////////////////////////////////
void VkPPRenderState::PushGroup(const FString &name)
{
GetVulkanFrameBuffer()->PushGroup(name);
}
void VkPPRenderState::PopGroup()
{
GetVulkanFrameBuffer()->PopGroup();
}
void VkPPRenderState::Draw()
{
auto fb = GetVulkanFrameBuffer();
auto pp = fb->GetPostprocess();
fb->GetRenderState()->EndRenderPass();
VkPPRenderPassKey key;
key.BlendMode = BlendMode;
key.InputTextures = Textures.Size();
key.Uniforms = Uniforms.Data.Size();
key.Shader = GetVkShader(Shader);
key.SwapChain = (Output.Type == PPTextureType::SwapChain);
key.ShadowMapBuffers = ShadowMapBuffers;
if (Output.Type == PPTextureType::PPTexture)
key.OutputFormat = GetVkTexture(Output.Texture)->Format;
else if (Output.Type == PPTextureType::SwapChain)
key.OutputFormat = GetVulkanFrameBuffer()->swapChain->swapChainFormat.format;
else if (Output.Type == PPTextureType::ShadowMap)
key.OutputFormat = VK_FORMAT_R32_SFLOAT;
else
key.OutputFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
if (Output.Type == PPTextureType::SceneColor)
{
key.StencilTest = 1;
key.Samples = fb->GetBuffers()->GetSceneSamples();
}
else
{
key.StencilTest = 0;
key.Samples = VK_SAMPLE_COUNT_1_BIT;
}
auto &passSetup = pp->mRenderPassSetup[key];
if (!passSetup)
passSetup.reset(new VkPPRenderPassSetup(key));
int framebufferWidth = 0, framebufferHeight = 0;
VulkanDescriptorSet *input = GetInput(passSetup.get(), Textures, ShadowMapBuffers);
VulkanFramebuffer *output = GetOutput(passSetup.get(), Output, key.StencilTest, framebufferWidth, framebufferHeight);
RenderScreenQuad(passSetup.get(), input, output, framebufferWidth, framebufferHeight, Viewport.left, Viewport.top, Viewport.width, Viewport.height, Uniforms.Data.Data(), Uniforms.Data.Size(), key.StencilTest);
// Advance to next PP texture if our output was sent there
if (Output.Type == PPTextureType::NextPipelineTexture)
{
pp->mCurrentPipelineImage = (pp->mCurrentPipelineImage + 1) % VkRenderBuffers::NumPipelineImages;
}
}
void VkPPRenderState::RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescriptorSet *descriptorSet, VulkanFramebuffer *framebuffer, int framebufferWidth, int framebufferHeight, int x, int y, int width, int height, const void *pushConstants, uint32_t pushConstantsSize, bool stencilTest)
{
auto fb = GetVulkanFrameBuffer();
auto cmdbuffer = fb->GetDrawCommands();
VkViewport viewport = { };
viewport.x = (float)x;
viewport.y = (float)y;
viewport.width = (float)width;
viewport.height = (float)height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
VkRect2D scissor = { };
scissor.offset.x = 0;
scissor.offset.y = 0;
scissor.extent.width = framebufferWidth;
scissor.extent.height = framebufferHeight;
RenderPassBegin beginInfo;
beginInfo.setRenderPass(passSetup->RenderPass.get());
beginInfo.setRenderArea(0, 0, framebufferWidth, framebufferHeight);
beginInfo.setFramebuffer(framebuffer);
beginInfo.addClearColor(0.0f, 0.0f, 0.0f, 1.0f);
VkBuffer vertexBuffers[] = { static_cast<VKVertexBuffer*>(screen->mVertexData->GetBufferObjects().first)->mBuffer->buffer };
VkDeviceSize offsets[] = { 0 };
cmdbuffer->beginRenderPass(beginInfo);
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->Pipeline.get());
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->PipelineLayout.get(), 0, descriptorSet);
cmdbuffer->bindVertexBuffers(0, 1, vertexBuffers, offsets);
cmdbuffer->setViewport(0, 1, &viewport);
cmdbuffer->setScissor(0, 1, &scissor);
if (stencilTest)
cmdbuffer->setStencilReference(VK_STENCIL_FRONT_AND_BACK, screen->stencilValue);
if (pushConstantsSize > 0)
cmdbuffer->pushConstants(passSetup->PipelineLayout.get(), VK_SHADER_STAGE_FRAGMENT_BIT, 0, pushConstantsSize, pushConstants);
cmdbuffer->draw(3, 1, FFlatVertexBuffer::PRESENT_INDEX, 0);
cmdbuffer->endRenderPass();
}
VulkanDescriptorSet *VkPPRenderState::GetInput(VkPPRenderPassSetup *passSetup, const TArray<PPTextureInput> &textures, bool bindShadowMapBuffers)
{
auto fb = GetVulkanFrameBuffer();
auto pp = fb->GetPostprocess();
auto descriptors = pp->AllocateDescriptorSet(passSetup->DescriptorLayout.get());
descriptors->SetDebugName("VkPostprocess.descriptors");
WriteDescriptors write;
VkImageTransition imageTransition;
for (unsigned int index = 0; index < textures.Size(); index++)
{
const PPTextureInput &input = textures[index];
VulkanSampler *sampler = pp->GetSampler(input.Filter, input.Wrap);
VkTextureImage *tex = GetTexture(input.Type, input.Texture);
write.addCombinedImageSampler(descriptors.get(), index, tex->DepthOnlyView ? tex->DepthOnlyView.get() : tex->View.get(), sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
imageTransition.addImage(tex, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
}
if (bindShadowMapBuffers)
{
write.addBuffer(descriptors.get(), LIGHTNODES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightNodes->mBuffer.get());
write.addBuffer(descriptors.get(), LIGHTLINES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightLines->mBuffer.get());
write.addBuffer(descriptors.get(), LIGHTLIST_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightList->mBuffer.get());
}
write.updateSets(fb->device);
imageTransition.execute(fb->GetDrawCommands());
VulkanDescriptorSet *set = descriptors.get();
fb->FrameDeleteList.Descriptors.push_back(std::move(descriptors));
return set;
}
VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, const PPOutput &output, bool stencilTest, int &framebufferWidth, int &framebufferHeight)
{
auto fb = GetVulkanFrameBuffer();
VkTextureImage *tex = GetTexture(output.Type, output.Texture);
VkImageView view;
std::unique_ptr<VulkanFramebuffer> *framebufferptr = nullptr;
int w, h;
if (tex)
{
VkImageTransition imageTransition;
imageTransition.addImage(tex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, output.Type == PPTextureType::NextPipelineTexture);
if (stencilTest)
imageTransition.addImage(&fb->GetBuffers()->SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false);
imageTransition.execute(fb->GetDrawCommands());
view = tex->View->view;
w = tex->Image->width;
h = tex->Image->height;
framebufferptr = &tex->PPFramebuffer;
}
else
{
view = fb->swapChain->swapChainImageViews[fb->presentImageIndex];
framebufferptr = &fb->swapChain->framebuffers[fb->presentImageIndex];
w = fb->swapChain->actualExtent.width;
h = fb->swapChain->actualExtent.height;
}
auto &framebuffer = *framebufferptr;
if (!framebuffer)
{
FramebufferBuilder builder;
builder.setRenderPass(passSetup->RenderPass.get());
builder.setSize(w, h);
builder.addAttachment(view);
if (stencilTest)
builder.addAttachment(fb->GetBuffers()->SceneDepthStencil.View.get());
framebuffer = builder.create(GetVulkanFrameBuffer()->device);
}
framebufferWidth = w;
framebufferHeight = h;
return framebuffer.get();
}
VkTextureImage *VkPPRenderState::GetTexture(const PPTextureType &type, PPTexture *pptexture)
{
auto fb = GetVulkanFrameBuffer();
if (type == PPTextureType::CurrentPipelineTexture || type == PPTextureType::NextPipelineTexture)
{
int idx = fb->GetPostprocess()->mCurrentPipelineImage;
if (type == PPTextureType::NextPipelineTexture)
idx = (idx + 1) % VkRenderBuffers::NumPipelineImages;
return &fb->GetBuffers()->PipelineImage[idx];
}
else if (type == PPTextureType::PPTexture)
{
auto vktex = GetVkTexture(pptexture);
return &vktex->TexImage;
}
else if (type == PPTextureType::SceneColor)
{
return &fb->GetBuffers()->SceneColor;
}
else if (type == PPTextureType::SceneNormal)
{
return &fb->GetBuffers()->SceneNormal;
}
else if (type == PPTextureType::SceneFog)
{
return &fb->GetBuffers()->SceneFog;
}
else if (type == PPTextureType::SceneDepth)
{
return &fb->GetBuffers()->SceneDepthStencil;
}
else if (type == PPTextureType::ShadowMap)
{
return &fb->GetBuffers()->Shadowmap;
}
else if (type == PPTextureType::SwapChain)
{
return nullptr;
}
else
{
I_FatalError("VkPPRenderState::GetTexture not implemented yet for this texture type");
return nullptr;
}
}
VkPPShader *VkPPRenderState::GetVkShader(PPShader *shader)
{
if (!shader->Backend)
shader->Backend = std::make_unique<VkPPShader>(shader);
return static_cast<VkPPShader*>(shader->Backend.get());
}
VkPPTexture *VkPPRenderState::GetVkTexture(PPTexture *texture)
{
if (!texture->Backend)
texture->Backend = std::make_unique<VkPPTexture>(texture);
return static_cast<VkPPTexture*>(texture->Backend.get());
}
/////////////////////////////////////////////////////////////////////////////
VkPPRenderPassSetup::VkPPRenderPassSetup(const VkPPRenderPassKey &key)
{
CreateDescriptorLayout(key);
CreatePipelineLayout(key);
CreateRenderPass(key);
CreatePipeline(key);
}
void VkPPRenderPassSetup::CreateDescriptorLayout(const VkPPRenderPassKey &key)
{
DescriptorSetLayoutBuilder builder;
for (int i = 0; i < key.InputTextures; i++)
builder.addBinding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
if (key.ShadowMapBuffers)
{
builder.addBinding(LIGHTNODES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
builder.addBinding(LIGHTLINES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
builder.addBinding(LIGHTLIST_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
}
DescriptorLayout = builder.create(GetVulkanFrameBuffer()->device);
DescriptorLayout->SetDebugName("VkPPRenderPassSetup.DescriptorLayout");
}
void VkPPRenderPassSetup::CreatePipelineLayout(const VkPPRenderPassKey &key)
{
PipelineLayoutBuilder builder;
builder.addSetLayout(DescriptorLayout.get());
if (key.Uniforms > 0)
builder.addPushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 0, key.Uniforms);
PipelineLayout = builder.create(GetVulkanFrameBuffer()->device);
PipelineLayout->SetDebugName("VkPPRenderPassSetup.PipelineLayout");
}
void VkPPRenderPassSetup::CreatePipeline(const VkPPRenderPassKey &key)
{
GraphicsPipelineBuilder builder;
builder.addVertexShader(key.Shader->VertexShader.get());
builder.addFragmentShader(key.Shader->FragmentShader.get());
builder.addVertexBufferBinding(0, sizeof(FFlatVertex));
builder.addVertexAttribute(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(FFlatVertex, x));
builder.addVertexAttribute(1, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(FFlatVertex, u));
builder.addDynamicState(VK_DYNAMIC_STATE_VIEWPORT);
builder.addDynamicState(VK_DYNAMIC_STATE_SCISSOR);
// Note: the actual values are ignored since we use dynamic viewport+scissor states
builder.setViewport(0.0f, 0.0f, 320.0f, 200.0f);
builder.setScissor(0, 0, 320, 200);
if (key.StencilTest)
{
builder.addDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
builder.setDepthStencilEnable(false, false, true);
builder.setStencil(VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_EQUAL, 0xffffffff, 0xffffffff, 0);
}
builder.setTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
builder.setBlendMode(key.BlendMode);
builder.setRasterizationSamples(key.Samples);
builder.setLayout(PipelineLayout.get());
builder.setRenderPass(RenderPass.get());
Pipeline = builder.create(GetVulkanFrameBuffer()->device);
Pipeline->SetDebugName("VkPPRenderPassSetup.Pipeline");
}
void VkPPRenderPassSetup::CreateRenderPass(const VkPPRenderPassKey &key)
{
RenderPassBuilder builder;
if (key.SwapChain)
builder.addAttachment(key.OutputFormat, key.Samples, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
else
builder.addAttachment(key.OutputFormat, key.Samples, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
if (key.StencilTest)
{
builder.addDepthStencilAttachment(
GetVulkanFrameBuffer()->GetBuffers()->SceneDepthStencilFormat, key.Samples,
VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
}
builder.addSubpass();
builder.addSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
if (key.StencilTest)
{
builder.addSubpassDepthStencilAttachmentRef(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
builder.addExternalSubpassDependency(
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT);
}
else
{
builder.addExternalSubpassDependency(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT);
}
RenderPass = builder.create(GetVulkanFrameBuffer()->device);
RenderPass->SetDebugName("VkPPRenderPassSetup.RenderPass");
}

View file

@ -14,35 +14,15 @@ class FString;
class VkPPShader;
class VkPPTexture;
class VkPPRenderPassSetup;
class PipelineBarrier;
class VkPPRenderPassKey
{
public:
VkPPShader *Shader;
int Uniforms;
int InputTextures;
PPBlendMode BlendMode;
VkFormat OutputFormat;
int SwapChain;
int ShadowMapBuffers;
int StencilTest;
VkSampleCountFlagBits Samples;
bool operator<(const VkPPRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) < 0; }
bool operator==(const VkPPRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) == 0; }
bool operator!=(const VkPPRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) != 0; }
};
class VulkanFrameBuffer;
class VkPostprocess
{
public:
VkPostprocess();
VkPostprocess(VulkanFrameBuffer* fb);
~VkPostprocess();
void RenderBuffersReset();
void SetActiveRenderTarget();
void PostProcessScene(int fixedcm, float flash, const std::function<void()> &afterBloomDrawEndScene2D);
@ -58,76 +38,14 @@ public:
void BlitCurrentToImage(VkTextureImage *image, VkImageLayout finallayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
void DrawPresentTexture(const IntRect &box, bool applyGamma, bool screenshot);
int GetCurrentPipelineImage() const { return mCurrentPipelineImage; }
private:
void NextEye(int eyeCount);
std::unique_ptr<VulkanDescriptorSet> AllocateDescriptorSet(VulkanDescriptorSetLayout *layout);
VulkanSampler *GetSampler(PPFilterMode filter, PPWrapMode wrap);
VulkanFrameBuffer* fb = nullptr;
std::array<std::unique_ptr<VulkanSampler>, 4> mSamplers;
std::map<VkPPRenderPassKey, std::unique_ptr<VkPPRenderPassSetup>> mRenderPassSetup;
std::unique_ptr<VulkanDescriptorPool> mDescriptorPool;
int mCurrentPipelineImage = 0;
friend class VkPPRenderState;
};
class VkPPShader : public PPShaderBackend
{
public:
VkPPShader(PPShader *shader);
std::unique_ptr<VulkanShader> VertexShader;
std::unique_ptr<VulkanShader> FragmentShader;
private:
FString LoadShaderCode(const FString &lumpname, const FString &defines, int version);
};
class VkPPTexture : public PPTextureBackend
{
public:
VkPPTexture(PPTexture *texture);
~VkPPTexture();
VkTextureImage TexImage;
std::unique_ptr<VulkanBuffer> Staging;
VkFormat Format;
};
class VkPPRenderPassSetup
{
public:
VkPPRenderPassSetup(const VkPPRenderPassKey &key);
std::unique_ptr<VulkanDescriptorSetLayout> DescriptorLayout;
std::unique_ptr<VulkanPipelineLayout> PipelineLayout;
std::unique_ptr<VulkanRenderPass> RenderPass;
std::unique_ptr<VulkanPipeline> Pipeline;
private:
void CreateDescriptorLayout(const VkPPRenderPassKey &key);
void CreatePipelineLayout(const VkPPRenderPassKey &key);
void CreatePipeline(const VkPPRenderPassKey &key);
void CreateRenderPass(const VkPPRenderPassKey &key);
};
class VkPPRenderState : public PPRenderState
{
public:
void PushGroup(const FString &name) override;
void PopGroup() override;
void Draw() override;
private:
void RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescriptorSet *descriptorSet, VulkanFramebuffer *framebuffer, int framebufferWidth, int framebufferHeight, int x, int y, int width, int height, const void *pushConstants, uint32_t pushConstantsSize, bool stencilTest);
VulkanDescriptorSet *GetInput(VkPPRenderPassSetup *passSetup, const TArray<PPTextureInput> &textures, bool bindShadowMapBuffers);
VulkanFramebuffer *GetOutput(VkPPRenderPassSetup *passSetup, const PPOutput &output, bool stencilTest, int &framebufferWidth, int &framebufferHeight);
VkPPShader *GetVkShader(PPShader *shader);
VkPPTexture *GetVkTexture(PPTexture *texture);
VkTextureImage *GetTexture(const PPTextureType &type, PPTexture *tex);
};

View file

@ -0,0 +1,138 @@
/*
** Vulkan backend
** Copyright (c) 2016-2020 Magnus Norddahl
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
**
*/
#include "vk_pprenderstate.h"
#include "vk_postprocess.h"
#include "vulkan/system/vk_framebuffer.h"
#include "vulkan/system/vk_commandbuffer.h"
#include "vulkan/system/vk_swapchain.h"
#include "vulkan/system/vk_buffer.h"
#include "vulkan/shaders/vk_ppshader.h"
#include "vulkan/textures/vk_pptexture.h"
#include "vulkan/textures/vk_renderbuffers.h"
#include "vulkan/textures/vk_samplers.h"
#include "vulkan/textures/vk_texture.h"
#include "vulkan/renderer/vk_renderstate.h"
#include "vulkan/renderer/vk_descriptorset.h"
#include "flatvertices.h"
VkPPRenderState::VkPPRenderState(VulkanFrameBuffer* fb) : fb(fb)
{
}
void VkPPRenderState::PushGroup(const FString &name)
{
fb->GetCommands()->PushGroup(name);
}
void VkPPRenderState::PopGroup()
{
fb->GetCommands()->PopGroup();
}
void VkPPRenderState::Draw()
{
fb->GetRenderState()->EndRenderPass();
VkPPRenderPassKey key;
key.BlendMode = BlendMode;
key.InputTextures = Textures.Size();
key.Uniforms = Uniforms.Data.Size();
key.Shader = fb->GetShaderManager()->GetVkShader(Shader);
key.SwapChain = (Output.Type == PPTextureType::SwapChain);
key.ShadowMapBuffers = ShadowMapBuffers;
if (Output.Type == PPTextureType::PPTexture)
key.OutputFormat = fb->GetTextureManager()->GetTextureFormat(Output.Texture);
else if (Output.Type == PPTextureType::SwapChain)
key.OutputFormat = fb->GetCommands()->swapChain->swapChainFormat.format;
else if (Output.Type == PPTextureType::ShadowMap)
key.OutputFormat = VK_FORMAT_R32_SFLOAT;
else
key.OutputFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
if (Output.Type == PPTextureType::SceneColor)
{
key.StencilTest = 1;
key.Samples = fb->GetBuffers()->GetSceneSamples();
}
else
{
key.StencilTest = 0;
key.Samples = VK_SAMPLE_COUNT_1_BIT;
}
auto passSetup = fb->GetRenderPassManager()->GetPPRenderPass(key);
int framebufferWidth = 0, framebufferHeight = 0;
VulkanDescriptorSet *input = fb->GetDescriptorSetManager()->GetInput(passSetup, Textures, ShadowMapBuffers);
VulkanFramebuffer *output = fb->GetBuffers()->GetOutput(passSetup, Output, key.StencilTest, framebufferWidth, framebufferHeight);
RenderScreenQuad(passSetup, input, output, framebufferWidth, framebufferHeight, Viewport.left, Viewport.top, Viewport.width, Viewport.height, Uniforms.Data.Data(), Uniforms.Data.Size(), key.StencilTest);
// Advance to next PP texture if our output was sent there
if (Output.Type == PPTextureType::NextPipelineTexture)
{
auto pp = fb->GetPostprocess();
pp->mCurrentPipelineImage = (pp->mCurrentPipelineImage + 1) % VkRenderBuffers::NumPipelineImages;
}
}
void VkPPRenderState::RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescriptorSet *descriptorSet, VulkanFramebuffer *framebuffer, int framebufferWidth, int framebufferHeight, int x, int y, int width, int height, const void *pushConstants, uint32_t pushConstantsSize, bool stencilTest)
{
auto cmdbuffer = fb->GetCommands()->GetDrawCommands();
VkViewport viewport = { };
viewport.x = (float)x;
viewport.y = (float)y;
viewport.width = (float)width;
viewport.height = (float)height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
VkRect2D scissor = { };
scissor.offset.x = 0;
scissor.offset.y = 0;
scissor.extent.width = framebufferWidth;
scissor.extent.height = framebufferHeight;
RenderPassBegin beginInfo;
beginInfo.setRenderPass(passSetup->RenderPass.get());
beginInfo.setRenderArea(0, 0, framebufferWidth, framebufferHeight);
beginInfo.setFramebuffer(framebuffer);
beginInfo.addClearColor(0.0f, 0.0f, 0.0f, 1.0f);
VkBuffer vertexBuffers[] = { static_cast<VkHardwareVertexBuffer*>(screen->mVertexData->GetBufferObjects().first)->mBuffer->buffer };
VkDeviceSize offsets[] = { 0 };
cmdbuffer->beginRenderPass(beginInfo);
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->Pipeline.get());
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->PipelineLayout.get(), 0, descriptorSet);
cmdbuffer->bindVertexBuffers(0, 1, vertexBuffers, offsets);
cmdbuffer->setViewport(0, 1, &viewport);
cmdbuffer->setScissor(0, 1, &scissor);
if (stencilTest)
cmdbuffer->setStencilReference(VK_STENCIL_FRONT_AND_BACK, screen->stencilValue);
if (pushConstantsSize > 0)
cmdbuffer->pushConstants(passSetup->PipelineLayout.get(), VK_SHADER_STAGE_FRAGMENT_BIT, 0, pushConstantsSize, pushConstants);
cmdbuffer->draw(3, 1, FFlatVertexBuffer::PRESENT_INDEX, 0);
cmdbuffer->endRenderPass();
}

View file

@ -0,0 +1,27 @@
#pragma once
#include "hwrenderer/postprocessing/hw_postprocess.h"
#include "vulkan/system/vk_objects.h"
class VkPPRenderPassSetup;
class VkPPShader;
class VkPPTexture;
class VkTextureImage;
class VulkanFrameBuffer;
class VkPPRenderState : public PPRenderState
{
public:
VkPPRenderState(VulkanFrameBuffer* fb);
void PushGroup(const FString &name) override;
void PopGroup() override;
void Draw() override;
private:
void RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescriptorSet *descriptorSet, VulkanFramebuffer *framebuffer, int framebufferWidth, int framebufferHeight, int x, int y, int width, int height, const void *pushConstants, uint32_t pushConstantsSize, bool stencilTest);
VulkanFrameBuffer* fb = nullptr;
};

View file

@ -0,0 +1,283 @@
/*
** Vulkan backend
** Copyright (c) 2016-2020 Magnus Norddahl
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
**
*/
#include "vk_raytrace.h"
#include "vulkan/system/vk_builders.h"
#include "vulkan/system/vk_framebuffer.h"
#include "vulkan/system/vk_commandbuffer.h"
//#include "doom_levelmesh.h"
VkRaytrace::VkRaytrace(VulkanFrameBuffer* fb) : fb(fb)
{
NullMesh.MeshVertices.Push({ -1.0f, -1.0f, -1.0f });
NullMesh.MeshVertices.Push({ 1.0f, -1.0f, -1.0f });
NullMesh.MeshVertices.Push({ 1.0f, 1.0f, -1.0f });
NullMesh.MeshVertices.Push({ -1.0f, -1.0f, -1.0f });
NullMesh.MeshVertices.Push({ -1.0f, 1.0f, -1.0f });
NullMesh.MeshVertices.Push({ 1.0f, 1.0f, -1.0f });
NullMesh.MeshVertices.Push({ -1.0f, -1.0f, 1.0f });
NullMesh.MeshVertices.Push({ 1.0f, -1.0f, 1.0f });
NullMesh.MeshVertices.Push({ 1.0f, 1.0f, 1.0f });
NullMesh.MeshVertices.Push({ -1.0f, -1.0f, 1.0f });
NullMesh.MeshVertices.Push({ -1.0f, 1.0f, 1.0f });
NullMesh.MeshVertices.Push({ 1.0f, 1.0f, 1.0f });
for (int i = 0; i < 3 * 4; i++)
NullMesh.MeshElements.Push(i);
SetLevelMesh(nullptr);
}
void VkRaytrace::SetLevelMesh(hwrenderer::LevelMesh* mesh)
{
if (!mesh)
mesh = &NullMesh;
if (mesh != Mesh)
{
Reset();
Mesh = mesh;
if (fb->RaytracingEnabled())
{
CreateVulkanObjects();
}
}
}
void VkRaytrace::Reset()
{
auto deletelist = fb->GetCommands()->DrawDeleteList.get();
deletelist->Add(std::move(vertexBuffer));
deletelist->Add(std::move(indexBuffer));
deletelist->Add(std::move(transferBuffer));
deletelist->Add(std::move(blScratchBuffer));
deletelist->Add(std::move(blAccelStructBuffer));
deletelist->Add(std::move(blAccelStruct));
deletelist->Add(std::move(tlTransferBuffer));
deletelist->Add(std::move(tlScratchBuffer));
deletelist->Add(std::move(tlInstanceBuffer));
deletelist->Add(std::move(tlAccelStructBuffer));
deletelist->Add(std::move(tlAccelStruct));
}
void VkRaytrace::CreateVulkanObjects()
{
CreateVertexAndIndexBuffers();
CreateBottomLevelAccelerationStructure();
CreateTopLevelAccelerationStructure();
}
void VkRaytrace::CreateVertexAndIndexBuffers()
{
static_assert(sizeof(FVector3) == 3 * 4, "sizeof(FVector3) is not 12 bytes!");
size_t vertexbuffersize = (size_t)Mesh->MeshVertices.Size() * sizeof(FVector3);
size_t indexbuffersize = (size_t)Mesh->MeshElements.Size() * sizeof(uint32_t);
size_t transferbuffersize = vertexbuffersize + indexbuffersize;
size_t vertexoffset = 0;
size_t indexoffset = vertexoffset + vertexbuffersize;
transferBuffer = BufferBuilder()
.Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
.Size(transferbuffersize)
.DebugName("transferBuffer")
.Create(fb->device);
uint8_t* data = (uint8_t*)transferBuffer->Map(0, transferbuffersize);
memcpy(data + vertexoffset, Mesh->MeshVertices.Data(), vertexbuffersize);
memcpy(data + indexoffset, Mesh->MeshElements.Data(), indexbuffersize);
transferBuffer->Unmap();
vertexBuffer = BufferBuilder()
.Usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
.Size(vertexbuffersize)
.DebugName("vertexBuffer")
.Create(fb->device);
indexBuffer = BufferBuilder()
.Usage(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
.Size(indexbuffersize)
.DebugName("indexBuffer")
.Create(fb->device);
fb->GetCommands()->GetTransferCommands()->copyBuffer(transferBuffer.get(), vertexBuffer.get(), vertexoffset);
fb->GetCommands()->GetTransferCommands()->copyBuffer(transferBuffer.get(), indexBuffer.get(), indexoffset);
// Finish transfer before using it for building
PipelineBarrier()
.AddMemory(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT)
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR);
}
void VkRaytrace::CreateBottomLevelAccelerationStructure()
{
VkAccelerationStructureBuildGeometryInfoKHR buildInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR };
VkAccelerationStructureGeometryKHR accelStructBLDesc = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR };
VkAccelerationStructureGeometryKHR* geometries[] = { &accelStructBLDesc };
VkAccelerationStructureBuildRangeInfoKHR rangeInfo = {};
VkAccelerationStructureBuildRangeInfoKHR* rangeInfos[] = { &rangeInfo };
buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
buildInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
buildInfo.geometryCount = 1;
buildInfo.ppGeometries = geometries;
accelStructBLDesc.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
accelStructBLDesc.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
accelStructBLDesc.geometry.triangles = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR };
accelStructBLDesc.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
accelStructBLDesc.geometry.triangles.vertexData.deviceAddress = vertexBuffer->GetDeviceAddress();
accelStructBLDesc.geometry.triangles.vertexStride = sizeof(FVector3);
accelStructBLDesc.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
accelStructBLDesc.geometry.triangles.indexData.deviceAddress = indexBuffer->GetDeviceAddress();
accelStructBLDesc.geometry.triangles.maxVertex = Mesh->MeshVertices.Size() - 1;
//accelStructBLDesc.geometry.triangles.transformData = transformAddress; // optional; VkTransformMatrixKHR transfered to a buffer?
rangeInfo.primitiveCount = Mesh->MeshElements.Size() / 3;
uint32_t maxPrimitiveCount = rangeInfo.primitiveCount;
VkAccelerationStructureBuildSizesInfoKHR sizeInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR };
vkGetAccelerationStructureBuildSizesKHR(fb->device->device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo, &maxPrimitiveCount, &sizeInfo);
blAccelStructBuffer = BufferBuilder()
.Usage(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
.Size(sizeInfo.accelerationStructureSize)
.DebugName("blAccelStructBuffer")
.Create(fb->device);
VkAccelerationStructureKHR blAccelStructHandle = {};
VkAccelerationStructureCreateInfoKHR createInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR };
createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
createInfo.buffer = blAccelStructBuffer->buffer;
createInfo.size = sizeInfo.accelerationStructureSize;
VkResult result = vkCreateAccelerationStructureKHR(fb->device->device, &createInfo, nullptr, &blAccelStructHandle);
if (result != VK_SUCCESS)
throw std::runtime_error("vkCreateAccelerationStructureKHR failed");
blAccelStruct = std::make_unique<VulkanAccelerationStructure>(fb->device, blAccelStructHandle);
blAccelStruct->SetDebugName("blAccelStruct");
blScratchBuffer = BufferBuilder()
.Usage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
.Size(sizeInfo.buildScratchSize)
.DebugName("blScratchBuffer")
.Create(fb->device);
buildInfo.dstAccelerationStructure = blAccelStruct->accelstruct;
buildInfo.scratchData.deviceAddress = blScratchBuffer->GetDeviceAddress();
fb->GetCommands()->GetTransferCommands()->buildAccelerationStructures(1, &buildInfo, rangeInfos);
// Finish building before using it as input to a toplevel accel structure
PipelineBarrier()
.AddMemory(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR)
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR);
}
void VkRaytrace::CreateTopLevelAccelerationStructure()
{
VkAccelerationStructureInstanceKHR instance = {};
instance.transform.matrix[0][0] = 1.0f;
instance.transform.matrix[1][1] = 1.0f;
instance.transform.matrix[2][2] = 1.0f;
instance.mask = 0xff;
instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
instance.accelerationStructureReference = blAccelStruct->GetDeviceAddress();
tlTransferBuffer = BufferBuilder()
.Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
.Size(sizeof(VkAccelerationStructureInstanceKHR))
.DebugName("tlTransferBuffer")
.Create(fb->device);
auto data = (uint8_t*)tlTransferBuffer->Map(0, sizeof(VkAccelerationStructureInstanceKHR));
memcpy(data, &instance, sizeof(VkAccelerationStructureInstanceKHR));
tlTransferBuffer->Unmap();
tlInstanceBuffer = BufferBuilder()
.Usage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
.Size(sizeof(VkAccelerationStructureInstanceKHR))
.DebugName("tlInstanceBuffer")
.Create(fb->device);
fb->GetCommands()->GetTransferCommands()->copyBuffer(tlTransferBuffer.get(), tlInstanceBuffer.get());
// Finish transfering before using it as input
VkMemoryBarrier barrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER };
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
fb->GetCommands()->GetTransferCommands()->pipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, 0, 1, &barrier, 0, nullptr, 0, nullptr);
VkAccelerationStructureBuildGeometryInfoKHR buildInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR };
VkAccelerationStructureGeometryKHR accelStructTLDesc = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR };
VkAccelerationStructureGeometryKHR* geometries[] = { &accelStructTLDesc };
VkAccelerationStructureBuildRangeInfoKHR rangeInfo = {};
VkAccelerationStructureBuildRangeInfoKHR* rangeInfos[] = { &rangeInfo };
buildInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
buildInfo.geometryCount = 1;
buildInfo.ppGeometries = geometries;
buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
buildInfo.srcAccelerationStructure = VK_NULL_HANDLE;
accelStructTLDesc.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
accelStructTLDesc.geometry.instances = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR };
accelStructTLDesc.geometry.instances.data.deviceAddress = tlInstanceBuffer->GetDeviceAddress();
uint32_t maxInstanceCount = 1;
rangeInfo.primitiveCount = 1;
VkAccelerationStructureBuildSizesInfoKHR sizeInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR };
vkGetAccelerationStructureBuildSizesKHR(fb->device->device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo, &maxInstanceCount, &sizeInfo);
tlAccelStructBuffer = BufferBuilder()
.Usage(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
.Size(sizeInfo.accelerationStructureSize)
.DebugName("tlAccelStructBuffer")
.Create(fb->device);
VkAccelerationStructureKHR tlAccelStructHandle = {};
VkAccelerationStructureCreateInfoKHR createInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR };
createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
createInfo.buffer = tlAccelStructBuffer->buffer;
createInfo.size = sizeInfo.accelerationStructureSize;
VkResult result = vkCreateAccelerationStructureKHR(fb->device->device, &createInfo, nullptr, &tlAccelStructHandle);
if (result != VK_SUCCESS)
throw std::runtime_error("vkCreateAccelerationStructureKHR failed");
tlAccelStruct = std::make_unique<VulkanAccelerationStructure>(fb->device, tlAccelStructHandle);
tlScratchBuffer = BufferBuilder()
.Usage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
.Size(sizeInfo.buildScratchSize)
.DebugName("tlScratchBuffer")
.Create(fb->device);
buildInfo.dstAccelerationStructure = tlAccelStruct->accelstruct;
buildInfo.scratchData.deviceAddress = tlScratchBuffer->GetDeviceAddress();
fb->GetCommands()->GetTransferCommands()->buildAccelerationStructures(1, &buildInfo, rangeInfos);
// Finish building the accel struct before using as input in a fragment shader
PipelineBarrier()
.AddMemory(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_SHADER_READ_BIT)
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
}

View file

@ -0,0 +1,43 @@
#pragma once
#include "vulkan/system/vk_objects.h"
#include "hw_levelmesh.h"
class VulkanFrameBuffer;
class VkRaytrace
{
public:
VkRaytrace(VulkanFrameBuffer* fb);
void SetLevelMesh(hwrenderer::LevelMesh* mesh);
VulkanAccelerationStructure* GetAccelStruct() { return tlAccelStruct.get(); }
private:
void Reset();
void CreateVulkanObjects();
void CreateVertexAndIndexBuffers();
void CreateBottomLevelAccelerationStructure();
void CreateTopLevelAccelerationStructure();
VulkanFrameBuffer* fb = nullptr;
hwrenderer::LevelMesh NullMesh;
hwrenderer::LevelMesh* Mesh = nullptr;
std::unique_ptr<VulkanBuffer> vertexBuffer;
std::unique_ptr<VulkanBuffer> indexBuffer;
std::unique_ptr<VulkanBuffer> transferBuffer;
std::unique_ptr<VulkanBuffer> blScratchBuffer;
std::unique_ptr<VulkanBuffer> blAccelStructBuffer;
std::unique_ptr<VulkanAccelerationStructure> blAccelStruct;
std::unique_ptr<VulkanBuffer> tlTransferBuffer;
std::unique_ptr<VulkanBuffer> tlScratchBuffer;
std::unique_ptr<VulkanBuffer> tlInstanceBuffer;
std::unique_ptr<VulkanBuffer> tlAccelStructBuffer;
std::unique_ptr<VulkanAccelerationStructure> tlAccelStruct;
};

View file

@ -1,305 +0,0 @@
/*
** Vulkan backend
** Copyright (c) 2016-2020 Magnus Norddahl
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
**
*/
#include "vk_renderbuffers.h"
#include "vk_renderpass.h"
#include "vk_postprocess.h"
#include "vulkan/shaders/vk_shader.h"
#include "vulkan/system/vk_builders.h"
#include "vulkan/system/vk_framebuffer.h"
#include "hw_cvars.h"
VkRenderBuffers::VkRenderBuffers()
{
}
VkRenderBuffers::~VkRenderBuffers()
{
}
VkSampleCountFlagBits VkRenderBuffers::GetBestSampleCount()
{
auto fb = GetVulkanFrameBuffer();
const auto &limits = fb->device->PhysicalDevice.Properties.limits;
VkSampleCountFlags deviceSampleCounts = limits.sampledImageColorSampleCounts & limits.sampledImageDepthSampleCounts & limits.sampledImageStencilSampleCounts;
int requestedSamples = clamp((int)gl_multisample, 0, 64);
int samples = 1;
VkSampleCountFlags bit = VK_SAMPLE_COUNT_1_BIT;
VkSampleCountFlags best = bit;
while (samples <= requestedSamples)
{
if (deviceSampleCounts & bit)
{
best = bit;
}
samples <<= 1;
bit <<= 1;
}
return (VkSampleCountFlagBits)best;
}
void VkRenderBuffers::BeginFrame(int width, int height, int sceneWidth, int sceneHeight)
{
VkSampleCountFlagBits samples = GetBestSampleCount();
if (width != mWidth || height != mHeight || mSamples != samples)
{
auto fb = GetVulkanFrameBuffer();
fb->GetRenderPassManager()->RenderBuffersReset();
fb->GetPostprocess()->RenderBuffersReset();
}
if (width != mWidth || height != mHeight)
CreatePipeline(width, height);
if (width != mWidth || height != mHeight || mSamples != samples)
CreateScene(width, height, samples);
CreateShadowmap();
CreateLightmapSampler();
mWidth = width;
mHeight = height;
mSamples = samples;
mSceneWidth = sceneWidth;
mSceneHeight = sceneHeight;
}
void VkRenderBuffers::CreatePipeline(int width, int height)
{
auto fb = GetVulkanFrameBuffer();
for (int i = 0; i < NumPipelineImages; i++)
{
PipelineImage[i].reset();
}
VkImageTransition barrier;
for (int i = 0; i < NumPipelineImages; i++)
{
ImageBuilder builder;
builder.setSize(width, height);
builder.setFormat(VK_FORMAT_R16G16B16A16_SFLOAT);
builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
PipelineImage[i].Image = builder.create(fb->device);
PipelineImage[i].Image->SetDebugName("VkRenderBuffers.PipelineImage");
ImageViewBuilder viewbuilder;
viewbuilder.setImage(PipelineImage[i].Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT);
PipelineImage[i].View = viewbuilder.create(fb->device);
PipelineImage[i].View->SetDebugName("VkRenderBuffers.PipelineView");
barrier.addImage(&PipelineImage[i], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
}
barrier.execute(fb->GetDrawCommands());
}
void VkRenderBuffers::CreateScene(int width, int height, VkSampleCountFlagBits samples)
{
auto fb = GetVulkanFrameBuffer();
SceneColor.reset();
SceneDepthStencil.reset();
SceneNormal.reset();
SceneFog.reset();
CreateSceneColor(width, height, samples);
CreateSceneDepthStencil(width, height, samples);
CreateSceneNormal(width, height, samples);
CreateSceneFog(width, height, samples);
VkImageTransition barrier;
barrier.addImage(&SceneColor, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
barrier.addImage(&SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, true);
barrier.addImage(&SceneNormal, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
barrier.addImage(&SceneFog, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
barrier.execute(fb->GetDrawCommands());
}
void VkRenderBuffers::CreateSceneColor(int width, int height, VkSampleCountFlagBits samples)
{
auto fb = GetVulkanFrameBuffer();
ImageBuilder builder;
builder.setSize(width, height);
builder.setSamples(samples);
builder.setFormat(VK_FORMAT_R16G16B16A16_SFLOAT);
builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
SceneColor.Image = builder.create(fb->device);
SceneColor.Image->SetDebugName("VkRenderBuffers.SceneColor");
ImageViewBuilder viewbuilder;
viewbuilder.setImage(SceneColor.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT);
SceneColor.View = viewbuilder.create(fb->device);
SceneColor.View->SetDebugName("VkRenderBuffers.SceneColorView");
}
void VkRenderBuffers::CreateSceneDepthStencil(int width, int height, VkSampleCountFlagBits samples)
{
auto fb = GetVulkanFrameBuffer();
ImageBuilder builder;
builder.setSize(width, height);
builder.setSamples(samples);
builder.setFormat(SceneDepthStencilFormat);
builder.setUsage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
if (!builder.isFormatSupported(fb->device))
{
SceneDepthStencilFormat = VK_FORMAT_D32_SFLOAT_S8_UINT;
builder.setFormat(SceneDepthStencilFormat);
if (!builder.isFormatSupported(fb->device))
{
I_FatalError("This device does not support any of the required depth stencil image formats.");
}
}
SceneDepthStencil.Image = builder.create(fb->device);
SceneDepthStencil.Image->SetDebugName("VkRenderBuffers.SceneDepthStencil");
SceneDepthStencil.AspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
ImageViewBuilder viewbuilder;
viewbuilder.setImage(SceneDepthStencil.Image.get(), SceneDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
SceneDepthStencil.View = viewbuilder.create(fb->device);
SceneDepthStencil.View->SetDebugName("VkRenderBuffers.SceneDepthStencilView");
viewbuilder.setImage(SceneDepthStencil.Image.get(), SceneDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT);
SceneDepthStencil.DepthOnlyView = viewbuilder.create(fb->device);
SceneDepthStencil.DepthOnlyView->SetDebugName("VkRenderBuffers.SceneDepthView");
}
void VkRenderBuffers::CreateSceneFog(int width, int height, VkSampleCountFlagBits samples)
{
auto fb = GetVulkanFrameBuffer();
ImageBuilder builder;
builder.setSize(width, height);
builder.setSamples(samples);
builder.setFormat(VK_FORMAT_R8G8B8A8_UNORM);
builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
SceneFog.Image = builder.create(fb->device);
SceneFog.Image->SetDebugName("VkRenderBuffers.SceneFog");
ImageViewBuilder viewbuilder;
viewbuilder.setImage(SceneFog.Image.get(), VK_FORMAT_R8G8B8A8_UNORM);
SceneFog.View = viewbuilder.create(fb->device);
SceneFog.View->SetDebugName("VkRenderBuffers.SceneFogView");
}
void VkRenderBuffers::CreateSceneNormal(int width, int height, VkSampleCountFlagBits samples)
{
auto fb = GetVulkanFrameBuffer();
ImageBuilder builder;
builder.setSize(width, height);
builder.setSamples(samples);
builder.setFormat(SceneNormalFormat);
builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
if (!builder.isFormatSupported(fb->device, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
{
SceneNormalFormat = VK_FORMAT_R8G8B8A8_UNORM;
builder.setFormat(SceneNormalFormat);
}
SceneNormal.Image = builder.create(fb->device);
SceneNormal.Image->SetDebugName("VkRenderBuffers.SceneNormal");
ImageViewBuilder viewbuilder;
viewbuilder.setImage(SceneNormal.Image.get(), SceneNormalFormat);
SceneNormal.View = viewbuilder.create(fb->device);
SceneNormal.View->SetDebugName("VkRenderBuffers.SceneNormalView");
}
void VkRenderBuffers::CreateShadowmap()
{
if (Shadowmap.Image && Shadowmap.Image->width == gl_shadowmap_quality)
return;
Shadowmap.reset();
auto fb = GetVulkanFrameBuffer();
ImageBuilder builder;
builder.setSize(gl_shadowmap_quality, 1024);
builder.setFormat(VK_FORMAT_R32_SFLOAT);
builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
Shadowmap.Image = builder.create(fb->device);
Shadowmap.Image->SetDebugName("VkRenderBuffers.Shadowmap");
ImageViewBuilder viewbuilder;
viewbuilder.setImage(Shadowmap.Image.get(), VK_FORMAT_R32_SFLOAT);
Shadowmap.View = viewbuilder.create(fb->device);
Shadowmap.View->SetDebugName("VkRenderBuffers.ShadowmapView");
VkImageTransition barrier;
barrier.addImage(&Shadowmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true);
barrier.execute(fb->GetDrawCommands());
if (!ShadowmapSampler)
{
SamplerBuilder samplerBuilder;
samplerBuilder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST);
samplerBuilder.setMinFilter(VK_FILTER_NEAREST);
samplerBuilder.setMagFilter(VK_FILTER_NEAREST);
samplerBuilder.setAddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
ShadowmapSampler = samplerBuilder.create(fb->device);
ShadowmapSampler->SetDebugName("VkRenderBuffers.ShadowmapSampler");
}
}
void VkRenderBuffers::CreateLightmapSampler()
{
if (!Lightmap.Image)
{
auto fb = GetVulkanFrameBuffer();
ImageBuilder builder;
builder.setSize(1, 1);
builder.setFormat(VK_FORMAT_R16G16B16A16_SFLOAT);
builder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT);
Lightmap.Image = builder.create(fb->device);
Lightmap.Image->SetDebugName("VkRenderBuffers.Lightmap");
ImageViewBuilder viewbuilder;
viewbuilder.setType(VK_IMAGE_VIEW_TYPE_2D_ARRAY);
viewbuilder.setImage(Lightmap.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT);
Lightmap.View = viewbuilder.create(fb->device);
Lightmap.View->SetDebugName("VkRenderBuffers.LightmapView");
VkImageTransition barrier;
barrier.addImage(&Lightmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true);
barrier.execute(fb->GetDrawCommands());
}
if (!LightmapSampler)
{
auto fb = GetVulkanFrameBuffer();
SamplerBuilder builder;
builder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_LINEAR);
builder.setMinFilter(VK_FILTER_LINEAR);
builder.setMagFilter(VK_FILTER_LINEAR);
builder.setAddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
LightmapSampler = builder.create(fb->device);
LightmapSampler->SetDebugName("VkRenderBuffers.LightmapSampler");
}
}

View file

@ -21,61 +21,39 @@
*/
#include "vk_renderpass.h"
#include "vk_renderbuffers.h"
#include "vk_renderstate.h"
#include "vk_descriptorset.h"
#include "vk_raytrace.h"
#include "vulkan/textures/vk_renderbuffers.h"
#include "vulkan/textures/vk_samplers.h"
#include "vulkan/shaders/vk_shader.h"
#include "vulkan/shaders/vk_ppshader.h"
#include "vulkan/system/vk_builders.h"
#include "vulkan/system/vk_framebuffer.h"
#include "vulkan/system/vk_buffers.h"
#include "vulkan/system/vk_hwbuffer.h"
#include "flatvertices.h"
#include "hw_viewpointuniforms.h"
#include "v_2ddrawer.h"
VkRenderPassManager::VkRenderPassManager()
VkRenderPassManager::VkRenderPassManager(VulkanFrameBuffer* fb) : fb(fb)
{
}
VkRenderPassManager::~VkRenderPassManager()
{
DynamicSet.reset(); // Needed since it must come before destruction of DynamicDescriptorPool
}
void VkRenderPassManager::Init()
{
CreateDynamicSetLayout();
CreateDescriptorPool();
CreateDynamicSet();
CreateNullTexture();
}
void VkRenderPassManager::RenderBuffersReset()
{
RenderPassSetup.clear();
}
void VkRenderPassManager::TextureSetPoolReset()
{
if (auto fb = GetVulkanFrameBuffer())
{
auto &deleteList = fb->FrameDeleteList;
for (auto &desc : TextureDescriptorPools)
{
deleteList.DescriptorPools.push_back(std::move(desc));
}
}
NullTextureDescriptorSet.reset();
TextureDescriptorPools.clear();
TextureDescriptorSetsLeft = 0;
TextureDescriptorsLeft = 0;
PPRenderPassSetup.clear();
}
VkRenderPassSetup *VkRenderPassManager::GetRenderPass(const VkRenderPassKey &key)
{
auto &item = RenderPassSetup[key];
if (!item)
item.reset(new VkRenderPassSetup(key));
item.reset(new VkRenderPassSetup(fb, key));
return item.get();
}
@ -122,38 +100,6 @@ VkVertexFormat *VkRenderPassManager::GetVertexFormat(int index)
return &VertexFormats[index];
}
void VkRenderPassManager::CreateDynamicSetLayout()
{
DescriptorSetLayoutBuilder builder;
builder.addBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
builder.addBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
builder.addBinding(2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
builder.addBinding(3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
builder.addBinding(4, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
builder.addBinding(5, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
DynamicSetLayout = builder.create(GetVulkanFrameBuffer()->device);
DynamicSetLayout->SetDebugName("VkRenderPassManager.DynamicSetLayout");
}
VulkanDescriptorSetLayout *VkRenderPassManager::GetTextureSetLayout(int numLayers)
{
if (TextureSetLayouts.size() < (size_t)numLayers)
TextureSetLayouts.resize(numLayers);
auto &layout = TextureSetLayouts[numLayers - 1];
if (layout)
return layout.get();
DescriptorSetLayoutBuilder builder;
for (int i = 0; i < numLayers; i++)
{
builder.addBinding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
}
layout = builder.create(GetVulkanFrameBuffer()->device);
layout->SetDebugName("VkRenderPassManager.TextureSetLayout");
return layout.get();
}
VulkanPipelineLayout* VkRenderPassManager::GetPipelineLayout(int numLayers)
{
if (PipelineLayouts.size() <= (size_t)numLayers)
@ -163,157 +109,68 @@ VulkanPipelineLayout* VkRenderPassManager::GetPipelineLayout(int numLayers)
if (layout)
return layout.get();
auto descriptors = fb->GetDescriptorSetManager();
PipelineLayoutBuilder builder;
builder.addSetLayout(DynamicSetLayout.get());
builder.AddSetLayout(descriptors->GetFixedSetLayout());
builder.AddSetLayout(descriptors->GetHWBufferSetLayout());
if (numLayers != 0)
builder.addSetLayout(GetTextureSetLayout(numLayers));
builder.addPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstants));
layout = builder.create(GetVulkanFrameBuffer()->device);
layout->SetDebugName("VkRenderPassManager.PipelineLayout");
builder.AddSetLayout(descriptors->GetTextureSetLayout(numLayers));
builder.AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstants));
builder.DebugName("VkRenderPassManager.PipelineLayout");
layout = builder.Create(fb->device);
return layout.get();
}
void VkRenderPassManager::CreateDescriptorPool()
VkPPRenderPassSetup* VkRenderPassManager::GetPPRenderPass(const VkPPRenderPassKey& key)
{
DescriptorPoolBuilder builder;
builder.addPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 3);
builder.addPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1);
builder.addPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2);
builder.setMaxSets(1);
DynamicDescriptorPool = builder.create(GetVulkanFrameBuffer()->device);
DynamicDescriptorPool->SetDebugName("VkRenderPassManager.DynamicDescriptorPool");
}
void VkRenderPassManager::CreateDynamicSet()
{
DynamicSet = DynamicDescriptorPool->allocate(DynamicSetLayout.get());
if (!DynamicSet)
I_FatalError("CreateDynamicSet failed.\n");
}
void VkRenderPassManager::CreateNullTexture()
{
auto fb = GetVulkanFrameBuffer();
ImageBuilder imgbuilder;
imgbuilder.setFormat(VK_FORMAT_R8G8B8A8_UNORM);
imgbuilder.setSize(1, 1);
imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT);
NullTexture = imgbuilder.create(fb->device);
NullTexture->SetDebugName("VkRenderPassManager.NullTexture");
ImageViewBuilder viewbuilder;
viewbuilder.setImage(NullTexture.get(), VK_FORMAT_R8G8B8A8_UNORM);
NullTextureView = viewbuilder.create(fb->device);
NullTextureView->SetDebugName("VkRenderPassManager.NullTextureView");
PipelineBarrier barrier;
barrier.addImage(NullTexture.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 0, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT);
barrier.execute(fb->GetTransferCommands(), VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
}
VulkanDescriptorSet* VkRenderPassManager::GetNullTextureDescriptorSet()
{
if (!NullTextureDescriptorSet)
{
NullTextureDescriptorSet = AllocateTextureDescriptorSet(SHADER_MIN_REQUIRED_TEXTURE_LAYERS);
auto fb = GetVulkanFrameBuffer();
WriteDescriptors update;
for (int i = 0; i < SHADER_MIN_REQUIRED_TEXTURE_LAYERS; i++)
{
update.addCombinedImageSampler(NullTextureDescriptorSet.get(), i, NullTextureView.get(), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
update.updateSets(fb->device);
}
return NullTextureDescriptorSet.get();
}
VulkanImageView* VkRenderPassManager::GetNullTextureView()
{
return NullTextureView.get();
}
void VkRenderPassManager::UpdateDynamicSet()
{
auto fb = GetVulkanFrameBuffer();
// In some rare cases drawing commands may already have been created before VulkanFrameBuffer::BeginFrame is called.
// Make sure there there are no active command buffers using DynamicSet when we update it:
fb->GetRenderState()->EndRenderPass();
fb->WaitForCommands(false);
WriteDescriptors update;
update.addBuffer(DynamicSet.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->ViewpointUBO->mBuffer.get(), 0, sizeof(HWViewpointUniforms));
update.addBuffer(DynamicSet.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightBufferSSO->mBuffer.get());
update.addBuffer(DynamicSet.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->MatrixBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(MatricesUBO));
update.addBuffer(DynamicSet.get(), 3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->StreamBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(StreamUBO));
update.addCombinedImageSampler(DynamicSet.get(), 4, fb->GetBuffers()->Shadowmap.View.get(), fb->GetBuffers()->ShadowmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
update.addCombinedImageSampler(DynamicSet.get(), 5, fb->GetBuffers()->Lightmap.View.get(), fb->GetBuffers()->LightmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
update.updateSets(fb->device);
}
std::unique_ptr<VulkanDescriptorSet> VkRenderPassManager::AllocateTextureDescriptorSet(int numLayers)
{
if (TextureDescriptorSetsLeft == 0 || TextureDescriptorsLeft < numLayers)
{
TextureDescriptorSetsLeft = 1000;
TextureDescriptorsLeft = 2000;
DescriptorPoolBuilder builder;
builder.addPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, TextureDescriptorsLeft);
builder.setMaxSets(TextureDescriptorSetsLeft);
TextureDescriptorPools.push_back(builder.create(GetVulkanFrameBuffer()->device));
TextureDescriptorPools.back()->SetDebugName("VkRenderPassManager.TextureDescriptorPool");
}
TextureDescriptorSetsLeft--;
TextureDescriptorsLeft -= numLayers;
return TextureDescriptorPools.back()->allocate(GetTextureSetLayout(numLayers));
auto& passSetup = PPRenderPassSetup[key];
if (!passSetup)
passSetup.reset(new VkPPRenderPassSetup(fb, key));
return passSetup.get();
}
/////////////////////////////////////////////////////////////////////////////
VkRenderPassSetup::VkRenderPassSetup(const VkRenderPassKey &key) : PassKey(key)
VkRenderPassSetup::VkRenderPassSetup(VulkanFrameBuffer* fb, const VkRenderPassKey &key) : PassKey(key), fb(fb)
{
}
std::unique_ptr<VulkanRenderPass> VkRenderPassSetup::CreateRenderPass(int clearTargets)
{
auto buffers = GetVulkanFrameBuffer()->GetBuffers();
auto buffers = fb->GetBuffers();
VkFormat drawBufferFormats[] = { VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R8G8B8A8_UNORM, buffers->SceneNormalFormat };
RenderPassBuilder builder;
builder.addAttachment(
builder.AddAttachment(
PassKey.DrawBufferFormat, (VkSampleCountFlagBits)PassKey.Samples,
(clearTargets & CT_Color) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
for (int i = 1; i < PassKey.DrawBuffers; i++)
{
builder.addAttachment(
builder.AddAttachment(
drawBufferFormats[i], buffers->GetSceneSamples(),
(clearTargets & CT_Color) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
}
if (PassKey.DepthStencil)
{
builder.addDepthStencilAttachment(
builder.AddDepthStencilAttachment(
buffers->SceneDepthStencilFormat, PassKey.DrawBufferFormat == VK_FORMAT_R8G8B8A8_UNORM ? VK_SAMPLE_COUNT_1_BIT : buffers->GetSceneSamples(),
(clearTargets & CT_Depth) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
(clearTargets & CT_Stencil) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
}
builder.addSubpass();
builder.AddSubpass();
for (int i = 0; i < PassKey.DrawBuffers; i++)
builder.addSubpassColorAttachmentRef(i, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
builder.AddSubpassColorAttachmentRef(i, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
if (PassKey.DepthStencil)
{
builder.addSubpassDepthStencilAttachmentRef(PassKey.DrawBuffers, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
builder.addExternalSubpassDependency(
builder.AddSubpassDepthStencilAttachmentRef(PassKey.DrawBuffers, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
builder.AddExternalSubpassDependency(
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
@ -321,15 +178,14 @@ std::unique_ptr<VulkanRenderPass> VkRenderPassSetup::CreateRenderPass(int clearT
}
else
{
builder.addExternalSubpassDependency(
builder.AddExternalSubpassDependency(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
}
auto renderpass = builder.create(GetVulkanFrameBuffer()->device);
renderpass->SetDebugName("VkRenderPassSetup.RenderPass");
return renderpass;
builder.DebugName("VkRenderPassSetup.RenderPass");
return builder.Create(fb->device);
}
VulkanRenderPass *VkRenderPassSetup::GetRenderPass(int clearTargets)
@ -349,7 +205,6 @@ VulkanPipeline *VkRenderPassSetup::GetPipeline(const VkPipelineKey &key)
std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipelineKey &key)
{
auto fb = GetVulkanFrameBuffer();
GraphicsPipelineBuilder builder;
VkShaderProgram *program;
@ -361,13 +216,13 @@ std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipeli
{
program = fb->GetShaderManager()->Get(key.EffectState, key.AlphaTest, PassKey.DrawBuffers > 1 ? GBUFFER_PASS : NORMAL_PASS);
}
builder.addVertexShader(program->vert.get());
builder.addFragmentShader(program->frag.get());
builder.AddVertexShader(program->vert.get());
builder.AddFragmentShader(program->frag.get());
const VkVertexFormat &vfmt = *fb->GetRenderPassManager()->GetVertexFormat(key.VertexFormat);
for (int i = 0; i < vfmt.NumBindingPoints; i++)
builder.addVertexBufferBinding(i, vfmt.Stride);
builder.AddVertexBufferBinding(i, vfmt.Stride);
const static VkFormat vkfmts[] = {
VK_FORMAT_R32G32B32A32_SFLOAT,
@ -383,7 +238,7 @@ std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipeli
for (size_t i = 0; i < vfmt.Attrs.size(); i++)
{
const auto &attr = vfmt.Attrs[i];
builder.addVertexAttribute(attr.location, attr.binding, vkfmts[attr.format], attr.offset);
builder.AddVertexAttribute(attr.location, attr.binding, vkfmts[attr.format], attr.offset);
inputLocations[attr.location] = true;
}
@ -391,22 +246,17 @@ std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipeli
for (int i = 0; i < 7; i++)
{
if (!inputLocations[i])
builder.addVertexAttribute(i, 0, VK_FORMAT_R32G32B32_SFLOAT, 0);
builder.AddVertexAttribute(i, 0, VK_FORMAT_R32G32B32_SFLOAT, 0);
}
builder.addDynamicState(VK_DYNAMIC_STATE_VIEWPORT);
builder.addDynamicState(VK_DYNAMIC_STATE_SCISSOR);
// builder.addDynamicState(VK_DYNAMIC_STATE_LINE_WIDTH);
builder.addDynamicState(VK_DYNAMIC_STATE_DEPTH_BIAS);
// builder.addDynamicState(VK_DYNAMIC_STATE_BLEND_CONSTANTS);
// builder.addDynamicState(VK_DYNAMIC_STATE_DEPTH_BOUNDS);
// builder.addDynamicState(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK);
// builder.addDynamicState(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK);
builder.addDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
builder.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT);
builder.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR);
builder.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_BIAS);
builder.AddDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
// Note: the actual values are ignored since we use dynamic viewport+scissor states
builder.setViewport(0.0f, 0.0f, 320.0f, 200.0f);
builder.setScissor(0, 0, 320, 200);
builder.Viewport(0.0f, 0.0f, 320.0f, 200.0f);
builder.Scissor(0, 0, 320, 200);
static const VkPrimitiveTopology vktopology[] = {
VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
@ -419,26 +269,130 @@ std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipeli
static const VkStencilOp op2vk[] = { VK_STENCIL_OP_KEEP, VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_DECREMENT_AND_CLAMP };
static const VkCompareOp depthfunc2vk[] = { VK_COMPARE_OP_LESS, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_ALWAYS };
builder.setTopology(vktopology[key.DrawType]);
builder.setDepthStencilEnable(key.DepthTest, key.DepthWrite, key.StencilTest);
builder.setDepthFunc(depthfunc2vk[key.DepthFunc]);
builder.Topology(vktopology[key.DrawType]);
builder.DepthStencilEnable(key.DepthTest, key.DepthWrite, key.StencilTest);
builder.DepthFunc(depthfunc2vk[key.DepthFunc]);
if (fb->device->UsedDeviceFeatures.depthClamp)
builder.setDepthClampEnable(key.DepthClamp);
builder.setDepthBias(key.DepthBias, 0.0f, 0.0f, 0.0f);
builder.DepthClampEnable(key.DepthClamp);
builder.DepthBias(key.DepthBias, 0.0f, 0.0f, 0.0f);
// Note: CCW and CW is intentionally swapped here because the vulkan and opengl coordinate systems differ.
// main.vp addresses this by patching up gl_Position.z, which has the side effect of flipping the sign of the front face calculations.
builder.setCull(key.CullMode == Cull_None ? VK_CULL_MODE_NONE : VK_CULL_MODE_BACK_BIT, key.CullMode == Cull_CW ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE);
builder.Cull(key.CullMode == Cull_None ? VK_CULL_MODE_NONE : VK_CULL_MODE_BACK_BIT, key.CullMode == Cull_CW ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE);
builder.setColorWriteMask((VkColorComponentFlags)key.ColorMask);
builder.setStencil(VK_STENCIL_OP_KEEP, op2vk[key.StencilPassOp], VK_STENCIL_OP_KEEP, VK_COMPARE_OP_EQUAL, 0xffffffff, 0xffffffff, 0);
builder.setBlendMode(key.RenderStyle);
builder.setSubpassColorAttachmentCount(PassKey.DrawBuffers);
builder.setRasterizationSamples((VkSampleCountFlagBits)PassKey.Samples);
builder.ColorWriteMask((VkColorComponentFlags)key.ColorMask);
builder.Stencil(VK_STENCIL_OP_KEEP, op2vk[key.StencilPassOp], VK_STENCIL_OP_KEEP, VK_COMPARE_OP_EQUAL, 0xffffffff, 0xffffffff, 0);
builder.BlendMode(key.RenderStyle);
builder.SubpassColorAttachmentCount(PassKey.DrawBuffers);
builder.RasterizationSamples((VkSampleCountFlagBits)PassKey.Samples);
builder.setLayout(fb->GetRenderPassManager()->GetPipelineLayout(key.NumTextureLayers));
builder.setRenderPass(GetRenderPass(0));
auto pipeline = builder.create(fb->device);
pipeline->SetDebugName("VkRenderPassSetup.Pipeline");
return pipeline;
builder.Layout(fb->GetRenderPassManager()->GetPipelineLayout(key.NumTextureLayers));
builder.RenderPass(GetRenderPass(0));
builder.DebugName("VkRenderPassSetup.Pipeline");
return builder.Create(fb->device);
}
/////////////////////////////////////////////////////////////////////////////
VkPPRenderPassSetup::VkPPRenderPassSetup(VulkanFrameBuffer* fb, const VkPPRenderPassKey& key) : fb(fb)
{
CreateDescriptorLayout(key);
CreatePipelineLayout(key);
CreateRenderPass(key);
CreatePipeline(key);
}
void VkPPRenderPassSetup::CreateDescriptorLayout(const VkPPRenderPassKey& key)
{
DescriptorSetLayoutBuilder builder;
for (int i = 0; i < key.InputTextures; i++)
builder.AddBinding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
if (key.ShadowMapBuffers)
{
builder.AddBinding(LIGHTNODES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
builder.AddBinding(LIGHTLINES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
builder.AddBinding(LIGHTLIST_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
}
builder.DebugName("VkPPRenderPassSetup.DescriptorLayout");
DescriptorLayout = builder.Create(fb->device);
}
void VkPPRenderPassSetup::CreatePipelineLayout(const VkPPRenderPassKey& key)
{
PipelineLayoutBuilder builder;
builder.AddSetLayout(DescriptorLayout.get());
if (key.Uniforms > 0)
builder.AddPushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 0, key.Uniforms);
builder.DebugName("VkPPRenderPassSetup.PipelineLayout");
PipelineLayout = builder.Create(fb->device);
}
void VkPPRenderPassSetup::CreatePipeline(const VkPPRenderPassKey& key)
{
GraphicsPipelineBuilder builder;
builder.AddVertexShader(key.Shader->VertexShader.get());
builder.AddFragmentShader(key.Shader->FragmentShader.get());
builder.AddVertexBufferBinding(0, sizeof(FFlatVertex));
builder.AddVertexAttribute(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(FFlatVertex, x));
builder.AddVertexAttribute(1, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(FFlatVertex, u));
builder.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT);
builder.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR);
// Note: the actual values are ignored since we use dynamic viewport+scissor states
builder.Viewport(0.0f, 0.0f, 320.0f, 200.0f);
builder.Scissor(0, 0, 320, 200);
if (key.StencilTest)
{
builder.AddDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
builder.DepthStencilEnable(false, false, true);
builder.Stencil(VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_EQUAL, 0xffffffff, 0xffffffff, 0);
}
builder.Topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
builder.BlendMode(key.BlendMode);
builder.RasterizationSamples(key.Samples);
builder.Layout(PipelineLayout.get());
builder.RenderPass(RenderPass.get());
builder.DebugName("VkPPRenderPassSetup.Pipeline");
Pipeline = builder.Create(fb->device);
}
void VkPPRenderPassSetup::CreateRenderPass(const VkPPRenderPassKey& key)
{
RenderPassBuilder builder;
if (key.SwapChain)
builder.AddAttachment(key.OutputFormat, key.Samples, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
else
builder.AddAttachment(key.OutputFormat, key.Samples, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
if (key.StencilTest)
{
builder.AddDepthStencilAttachment(
fb->GetBuffers()->SceneDepthStencilFormat, key.Samples,
VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
}
builder.AddSubpass();
builder.AddSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
if (key.StencilTest)
{
builder.AddSubpassDepthStencilAttachmentRef(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
builder.AddExternalSubpassDependency(
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT);
}
else
{
builder.AddExternalSubpassDependency(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT);
}
builder.DebugName("VkPPRenderPassSetup.RenderPass");
RenderPass = builder.Create(fb->device);
}

View file

@ -4,11 +4,13 @@
#include "vulkan/system/vk_objects.h"
#include "renderstyle.h"
#include "hwrenderer/data/buffers.h"
#include "hwrenderer/postprocessing/hw_postprocess.h"
#include "hw_renderstate.h"
#include <string.h>
#include <map>
class VKDataBuffer;
class VulkanFrameBuffer;
class VkPPShader;
class VkPipelineKey
{
@ -51,7 +53,7 @@ public:
class VkRenderPassSetup
{
public:
VkRenderPassSetup(const VkRenderPassKey &key);
VkRenderPassSetup(VulkanFrameBuffer* fb, const VkRenderPassKey &key);
VulkanRenderPass *GetRenderPass(int clearTargets);
VulkanPipeline *GetPipeline(const VkPipelineKey &key);
@ -63,6 +65,8 @@ public:
private:
std::unique_ptr<VulkanRenderPass> CreateRenderPass(int clearTargets);
std::unique_ptr<VulkanPipeline> CreatePipeline(const VkPipelineKey &key);
VulkanFrameBuffer* fb = nullptr;
};
class VkVertexFormat
@ -74,50 +78,64 @@ public:
int UseVertexData;
};
class VkPPRenderPassKey
{
public:
VkPPShader* Shader;
int Uniforms;
int InputTextures;
PPBlendMode BlendMode;
VkFormat OutputFormat;
int SwapChain;
int ShadowMapBuffers;
int StencilTest;
VkSampleCountFlagBits Samples;
bool operator<(const VkPPRenderPassKey& other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) < 0; }
bool operator==(const VkPPRenderPassKey& other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) == 0; }
bool operator!=(const VkPPRenderPassKey& other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) != 0; }
};
class VkPPRenderPassSetup
{
public:
VkPPRenderPassSetup(VulkanFrameBuffer* fb, const VkPPRenderPassKey& key);
std::unique_ptr<VulkanDescriptorSetLayout> DescriptorLayout;
std::unique_ptr<VulkanPipelineLayout> PipelineLayout;
std::unique_ptr<VulkanRenderPass> RenderPass;
std::unique_ptr<VulkanPipeline> Pipeline;
private:
void CreateDescriptorLayout(const VkPPRenderPassKey& key);
void CreatePipelineLayout(const VkPPRenderPassKey& key);
void CreatePipeline(const VkPPRenderPassKey& key);
void CreateRenderPass(const VkPPRenderPassKey& key);
VulkanFrameBuffer* fb = nullptr;
};
class VkRenderPassManager
{
public:
VkRenderPassManager();
VkRenderPassManager(VulkanFrameBuffer* fb);
~VkRenderPassManager();
void Init();
void RenderBuffersReset();
void UpdateDynamicSet();
void TextureSetPoolReset();
VkRenderPassSetup *GetRenderPass(const VkRenderPassKey &key);
int GetVertexFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs);
VkVertexFormat *GetVertexFormat(int index);
std::unique_ptr<VulkanDescriptorSet> AllocateTextureDescriptorSet(int numLayers);
VulkanPipelineLayout* GetPipelineLayout(int numLayers);
VulkanDescriptorSet* GetNullTextureDescriptorSet();
VulkanImageView* GetNullTextureView();
std::unique_ptr<VulkanDescriptorSetLayout> DynamicSetLayout;
std::map<VkRenderPassKey, std::unique_ptr<VkRenderPassSetup>> RenderPassSetup;
std::unique_ptr<VulkanDescriptorSet> DynamicSet;
VkPPRenderPassSetup* GetPPRenderPass(const VkPPRenderPassKey& key);
private:
void CreateDynamicSetLayout();
void CreateDescriptorPool();
void CreateDynamicSet();
void CreateNullTexture();
VulkanFrameBuffer* fb = nullptr;
VulkanDescriptorSetLayout *GetTextureSetLayout(int numLayers);
int TextureDescriptorSetsLeft = 0;
int TextureDescriptorsLeft = 0;
std::vector<std::unique_ptr<VulkanDescriptorPool>> TextureDescriptorPools;
std::unique_ptr<VulkanDescriptorPool> DynamicDescriptorPool;
std::vector<std::unique_ptr<VulkanDescriptorSetLayout>> TextureSetLayouts;
std::map<VkRenderPassKey, std::unique_ptr<VkRenderPassSetup>> RenderPassSetup;
std::vector<std::unique_ptr<VulkanPipelineLayout>> PipelineLayouts;
std::vector<VkVertexFormat> VertexFormats;
std::unique_ptr<VulkanImage> NullTexture;
std::unique_ptr<VulkanImageView> NullTextureView;
std::unique_ptr<VulkanDescriptorSet> NullTextureDescriptorSet;
std::map<VkPPRenderPassKey, std::unique_ptr<VkPPRenderPassSetup>> PPRenderPassSetup;
};

View file

@ -23,8 +23,11 @@
#include "vk_renderstate.h"
#include "vulkan/system/vk_framebuffer.h"
#include "vulkan/system/vk_builders.h"
#include "vulkan/system/vk_commandbuffer.h"
#include "vulkan/system/vk_buffer.h"
#include "vulkan/renderer/vk_renderpass.h"
#include "vulkan/renderer/vk_renderbuffers.h"
#include "vulkan/renderer/vk_descriptorset.h"
#include "vulkan/textures/vk_renderbuffers.h"
#include "vulkan/textures/vk_hwtexture.h"
#include "hw_skydome.h"
@ -39,7 +42,7 @@
CVAR(Int, vk_submit_size, 1000, 0);
EXTERN_CVAR(Bool, r_skipmats)
VkRenderState::VkRenderState()
VkRenderState::VkRenderState(VulkanFrameBuffer* fb) : fb(fb), mStreamBufferWriter(fb), mMatrixBufferWriter(fb)
{
Reset();
}
@ -182,7 +185,7 @@ void VkRenderState::Apply(int dt)
mApplyCount++;
if (mApplyCount >= vk_submit_size)
{
GetVulkanFrameBuffer()->FlushCommands(false);
fb->GetCommands()->FlushCommands(false);
mApplyCount = 0;
}
@ -195,7 +198,7 @@ void VkRenderState::Apply(int dt)
ApplyDepthBias();
ApplyPushConstants();
ApplyVertexBuffers();
ApplyDynamicSet();
ApplyHWBufferSet();
ApplyMaterial();
mNeedApply = false;
@ -216,7 +219,7 @@ void VkRenderState::ApplyRenderPass(int dt)
// Find a pipeline that matches our state
VkPipelineKey pipelineKey;
pipelineKey.DrawType = dt;
pipelineKey.VertexFormat = static_cast<VKVertexBuffer*>(mVertexBuffer)->VertexFormat;
pipelineKey.VertexFormat = static_cast<VkHardwareVertexBuffer*>(mVertexBuffer)->VertexFormat;
pipelineKey.RenderStyle = mRenderStyle;
pipelineKey.DepthTest = mDepthTest;
pipelineKey.DepthWrite = mDepthTest && mDepthWrite;
@ -251,7 +254,7 @@ void VkRenderState::ApplyRenderPass(int dt)
if (!inRenderPass)
{
mCommandBuffer = GetVulkanFrameBuffer()->GetDrawCommands();
mCommandBuffer = fb->GetCommands()->GetDrawCommands();
mScissorChanged = true;
mViewportChanged = true;
mStencilRefChanged = true;
@ -333,10 +336,9 @@ void VkRenderState::ApplyViewport()
void VkRenderState::ApplyStreamData()
{
auto fb = GetVulkanFrameBuffer();
auto passManager = fb->GetRenderPassManager();
mStreamData.useVertexData = passManager->GetVertexFormat(static_cast<VKVertexBuffer*>(mVertexBuffer)->VertexFormat)->UseVertexData;
mStreamData.useVertexData = passManager->GetVertexFormat(static_cast<VkHardwareVertexBuffer*>(mVertexBuffer)->VertexFormat)->UseVertexData;
if (mMaterial.mMaterial && mMaterial.mMaterial->Source())
mStreamData.timer = static_cast<float>((double)(screen->FrameTime - firstFrame) * (double)mMaterial.mMaterial->Source()->GetShaderSpeed() / 1000.);
@ -391,7 +393,6 @@ void VkRenderState::ApplyPushConstants()
mPushConstants.uLightIndex = mLightIndex;
mPushConstants.uDataIndex = mStreamBufferWriter.DataIndex();
auto fb = GetVulkanFrameBuffer();
auto passManager = fb->GetRenderPassManager();
mCommandBuffer->pushConstants(passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &mPushConstants);
}
@ -409,8 +410,8 @@ void VkRenderState::ApplyVertexBuffers()
{
if ((mVertexBuffer != mLastVertexBuffer || mVertexOffsets[0] != mLastVertexOffsets[0] || mVertexOffsets[1] != mLastVertexOffsets[1]) && mVertexBuffer)
{
auto vkbuf = static_cast<VKVertexBuffer*>(mVertexBuffer);
const VkVertexFormat *format = GetVulkanFrameBuffer()->GetRenderPassManager()->GetVertexFormat(vkbuf->VertexFormat);
auto vkbuf = static_cast<VkHardwareVertexBuffer*>(mVertexBuffer);
const VkVertexFormat *format = fb->GetRenderPassManager()->GetVertexFormat(vkbuf->VertexFormat);
VkBuffer vertexBuffers[2] = { vkbuf->mBuffer->buffer, vkbuf->mBuffer->buffer };
VkDeviceSize offsets[] = { mVertexOffsets[0] * format->Stride, mVertexOffsets[1] * format->Stride };
mCommandBuffer->bindVertexBuffers(0, 2, vertexBuffers, offsets);
@ -421,7 +422,7 @@ void VkRenderState::ApplyVertexBuffers()
if (mIndexBuffer != mLastIndexBuffer && mIndexBuffer)
{
mCommandBuffer->bindIndexBuffer(static_cast<VKIndexBuffer*>(mIndexBuffer)->mBuffer->buffer, 0, VK_INDEX_TYPE_UINT32);
mCommandBuffer->bindIndexBuffer(static_cast<VkHardwareIndexBuffer*>(mIndexBuffer)->mBuffer->buffer, 0, VK_INDEX_TYPE_UINT32);
mLastIndexBuffer = mIndexBuffer;
}
}
@ -430,29 +431,31 @@ void VkRenderState::ApplyMaterial()
{
if (mMaterial.mChanged)
{
auto fb = GetVulkanFrameBuffer();
auto passManager = fb->GetRenderPassManager();
auto descriptors = fb->GetDescriptorSetManager();
if (mMaterial.mMaterial && mMaterial.mMaterial->Source()->isHardwareCanvas()) static_cast<FCanvasTexture*>(mMaterial.mMaterial->Source()->GetTexture())->NeedUpdate();
VulkanDescriptorSet* descriptorset = mMaterial.mMaterial ? static_cast<VkMaterial*>(mMaterial.mMaterial)->GetDescriptorSet(mMaterial) : passManager->GetNullTextureDescriptorSet();
VulkanDescriptorSet* descriptorset = mMaterial.mMaterial ? static_cast<VkMaterial*>(mMaterial.mMaterial)->GetDescriptorSet(mMaterial) : descriptors->GetNullTextureDescriptorSet();
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 1, descriptorset);
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, fb->GetRenderPassManager()->GetPipelineLayout(mPipelineKey.NumTextureLayers), 0, fb->GetDescriptorSetManager()->GetFixedDescriptorSet());
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 2, descriptorset);
mMaterial.mChanged = false;
}
}
void VkRenderState::ApplyDynamicSet()
void VkRenderState::ApplyHWBufferSet()
{
auto fb = GetVulkanFrameBuffer();
uint32_t matrixOffset = mMatrixBufferWriter.Offset();
uint32_t streamDataOffset = mStreamBufferWriter.StreamDataOffset();
if (mViewpointOffset != mLastViewpointOffset || matrixOffset != mLastMatricesOffset || streamDataOffset != mLastStreamDataOffset)
{
auto passManager = fb->GetRenderPassManager();
auto descriptors = fb->GetDescriptorSetManager();
uint32_t offsets[3] = { mViewpointOffset, matrixOffset, streamDataOffset };
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 0, passManager->DynamicSet.get(), 3, offsets);
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 0, fb->GetDescriptorSetManager()->GetFixedDescriptorSet());
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 1, descriptors->GetHWBufferDescriptorSet(), 3, offsets);
mLastViewpointOffset = mViewpointOffset;
mLastMatricesOffset = matrixOffset;
@ -462,7 +465,7 @@ void VkRenderState::ApplyDynamicSet()
void VkRenderState::WaitForStreamBuffers()
{
GetVulkanFrameBuffer()->WaitForCommands(false);
fb->WaitForCommands(false);
mApplyCount = 0;
mStreamBufferWriter.Reset();
mMatrixBufferWriter.Reset();
@ -528,8 +531,6 @@ void VkRenderState::SetRenderTarget(VkTextureImage *image, VulkanImageView *dept
void VkRenderState::BeginRenderPass(VulkanCommandBuffer *cmdbuffer)
{
auto fb = GetVulkanFrameBuffer();
VkRenderPassKey key = {};
key.DrawBufferFormat = mRenderTarget.Format;
key.Samples = mRenderTarget.Samples;
@ -543,17 +544,17 @@ void VkRenderState::BeginRenderPass(VulkanCommandBuffer *cmdbuffer)
{
auto buffers = fb->GetBuffers();
FramebufferBuilder builder;
builder.setRenderPass(mPassSetup->GetRenderPass(0));
builder.setSize(mRenderTarget.Width, mRenderTarget.Height);
builder.addAttachment(mRenderTarget.Image->View.get());
builder.RenderPass(mPassSetup->GetRenderPass(0));
builder.Size(mRenderTarget.Width, mRenderTarget.Height);
builder.AddAttachment(mRenderTarget.Image->View.get());
if (key.DrawBuffers > 1)
builder.addAttachment(buffers->SceneFog.View.get());
builder.AddAttachment(buffers->SceneFog.View.get());
if (key.DrawBuffers > 2)
builder.addAttachment(buffers->SceneNormal.View.get());
builder.AddAttachment(buffers->SceneNormal.View.get());
if (key.DepthStencil)
builder.addAttachment(mRenderTarget.DepthStencil);
framebuffer = builder.create(GetVulkanFrameBuffer()->device);
framebuffer->SetDebugName("VkRenderPassSetup.Framebuffer");
builder.AddAttachment(mRenderTarget.DepthStencil);
builder.DebugName("VkRenderPassSetup.Framebuffer");
framebuffer = builder.Create(fb->device);
}
// Only clear depth+stencil if the render target actually has that
@ -583,7 +584,7 @@ void VkRenderStateMolten::Draw(int dt, int index, int count, bool apply)
if (dt == DT_TriangleFan)
{
IIndexBuffer *oldIndexBuffer = mIndexBuffer;
mIndexBuffer = GetVulkanFrameBuffer()->FanToTrisIndexBuffer.get();
mIndexBuffer = fb->GetBufferManager()->FanToTrisIndexBuffer.get();
if (apply || mNeedApply)
Apply(DT_Triangles);

View file

@ -1,7 +1,7 @@
#pragma once
#include "vulkan/system/vk_buffers.h"
#include "vulkan/system/vk_hwbuffer.h"
#include "vulkan/shaders/vk_shader.h"
#include "vulkan/renderer/vk_renderpass.h"
#include "vulkan/renderer/vk_streambuffer.h"
@ -11,13 +11,14 @@
#include "hw_renderstate.h"
#include "hw_material.h"
class VulkanFrameBuffer;
class VkRenderPassSetup;
class VkTextureImage;
class VkRenderState : public FRenderState
{
public:
VkRenderState();
VkRenderState(VulkanFrameBuffer* fb);
virtual ~VkRenderState() = default;
// Draw commands
@ -59,13 +60,15 @@ protected:
void ApplyStreamData();
void ApplyMatrices();
void ApplyPushConstants();
void ApplyDynamicSet();
void ApplyHWBufferSet();
void ApplyVertexBuffers();
void ApplyMaterial();
void BeginRenderPass(VulkanCommandBuffer *cmdbuffer);
void WaitForStreamBuffers();
VulkanFrameBuffer* fb = nullptr;
bool mDepthClamp = true;
VulkanCommandBuffer *mCommandBuffer = nullptr;
VkPipelineKey mPipelineKey = {};

View file

@ -23,37 +23,12 @@
#include "vk_renderstate.h"
#include "vulkan/system/vk_framebuffer.h"
#include "vulkan/system/vk_builders.h"
#include "vulkan/system/vk_buffer.h"
#include "vulkan/renderer/vk_streambuffer.h"
VkStreamBuffer::VkStreamBuffer(size_t structSize, size_t count)
VkStreamBufferWriter::VkStreamBufferWriter(VulkanFrameBuffer* fb)
{
mBlockSize = static_cast<uint32_t>((structSize + screen->uniformblockalignment - 1) / screen->uniformblockalignment * screen->uniformblockalignment);
UniformBuffer = (VKDataBuffer*)GetVulkanFrameBuffer()->CreateDataBuffer(-1, false, false);
UniformBuffer->SetData(mBlockSize * count, nullptr, BufferUsageType::Persistent);
}
VkStreamBuffer::~VkStreamBuffer()
{
delete UniformBuffer;
}
uint32_t VkStreamBuffer::NextStreamDataBlock()
{
mStreamDataOffset += mBlockSize;
if (mStreamDataOffset + (size_t)mBlockSize >= UniformBuffer->Size())
{
mStreamDataOffset = 0;
return 0xffffffff;
}
return mStreamDataOffset;
}
/////////////////////////////////////////////////////////////////////////////
VkStreamBufferWriter::VkStreamBufferWriter()
{
mBuffer = GetVulkanFrameBuffer()->StreamBuffer;
mBuffer = fb->GetBufferManager()->StreamBuffer.get();
}
bool VkStreamBufferWriter::Write(const StreamData& data)
@ -80,9 +55,9 @@ void VkStreamBufferWriter::Reset()
/////////////////////////////////////////////////////////////////////////////
VkMatrixBufferWriter::VkMatrixBufferWriter()
VkMatrixBufferWriter::VkMatrixBufferWriter(VulkanFrameBuffer* fb)
{
mBuffer = GetVulkanFrameBuffer()->MatrixBuffer;
mBuffer = fb->GetBufferManager()->MatrixBuffer.get();
mIdentityMatrix.loadIdentity();
}

View file

@ -1,7 +1,7 @@
#pragma once
#include "vulkan/system/vk_buffers.h"
#include "vulkan/system/vk_hwbuffer.h"
#include "vulkan/shaders/vk_shader.h"
class VkStreamBuffer;
@ -10,7 +10,7 @@ class VkMatrixBuffer;
class VkStreamBufferWriter
{
public:
VkStreamBufferWriter();
VkStreamBufferWriter(VulkanFrameBuffer* fb);
bool Write(const StreamData& data);
void Reset();
@ -27,7 +27,7 @@ private:
class VkMatrixBufferWriter
{
public:
VkMatrixBufferWriter();
VkMatrixBufferWriter(VulkanFrameBuffer* fb);
bool Write(const VSMatrix& modelMatrix, bool modelMatrixEnabled, const VSMatrix& textureMatrix, bool textureMatrixEnabled);
void Reset();
@ -40,19 +40,3 @@ private:
VSMatrix mIdentityMatrix;
uint32_t mOffset = 0;
};
class VkStreamBuffer
{
public:
VkStreamBuffer(size_t structSize, size_t count);
~VkStreamBuffer();
uint32_t NextStreamDataBlock();
void Reset() { mStreamDataOffset = 0; }
VKDataBuffer* UniformBuffer = nullptr;
private:
uint32_t mBlockSize = 0;
uint32_t mStreamDataOffset = 0;
};

View file

@ -0,0 +1,77 @@
/*
** Vulkan backend
** Copyright (c) 2016-2020 Magnus Norddahl
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
**
*/
#include "vk_ppshader.h"
#include "vk_shader.h"
#include "vulkan/system/vk_framebuffer.h"
#include "vulkan/system/vk_builders.h"
#include "vulkan/system/vk_commandbuffer.h"
#include "filesystem.h"
VkPPShader::VkPPShader(VulkanFrameBuffer* fb, PPShader *shader) : fb(fb)
{
FString prolog;
if (!shader->Uniforms.empty())
prolog = UniformBlockDecl::Create("Uniforms", shader->Uniforms, -1);
prolog += shader->Defines;
VertexShader = ShaderBuilder()
.VertexShader(LoadShaderCode(shader->VertexShader, "", shader->Version))
.DebugName(shader->VertexShader.GetChars())
.Create(shader->VertexShader.GetChars(), fb->device);
FragmentShader = ShaderBuilder()
.FragmentShader(LoadShaderCode(shader->FragmentShader, prolog, shader->Version))
.DebugName(shader->FragmentShader.GetChars())
.Create(shader->FragmentShader.GetChars(), fb->device);
fb->GetShaderManager()->AddVkPPShader(this);
}
VkPPShader::~VkPPShader()
{
if (fb)
fb->GetShaderManager()->RemoveVkPPShader(this);
}
void VkPPShader::Reset()
{
if (fb)
{
fb->GetCommands()->DrawDeleteList->Add(std::move(VertexShader));
fb->GetCommands()->DrawDeleteList->Add(std::move(FragmentShader));
}
}
FString VkPPShader::LoadShaderCode(const FString &lumpName, const FString &defines, int version)
{
int lump = fileSystem.CheckNumForFullName(lumpName);
if (lump == -1) I_FatalError("Unable to load '%s'", lumpName.GetChars());
FString code = fileSystem.ReadFile(lump).GetString().GetChars();
FString patchedCode;
patchedCode.AppendFormat("#version %d\n", 450);
patchedCode << defines;
patchedCode << "#line 1\n";
patchedCode << code;
return patchedCode;
}

View file

@ -0,0 +1,26 @@
#pragma once
#include "hwrenderer/postprocessing/hw_postprocess.h"
#include "vulkan/system/vk_objects.h"
#include <list>
class VulkanFrameBuffer;
class VkPPShader : public PPShaderBackend
{
public:
VkPPShader(VulkanFrameBuffer* fb, PPShader *shader);
~VkPPShader();
void Reset();
VulkanFrameBuffer* fb = nullptr;
std::list<VkPPShader*>::iterator it;
std::unique_ptr<VulkanShader> VertexShader;
std::unique_ptr<VulkanShader> FragmentShader;
private:
FString LoadShaderCode(const FString &lumpname, const FString &defines, int version);
};

View file

@ -21,7 +21,9 @@
*/
#include "vk_shader.h"
#include "vk_ppshader.h"
#include "vulkan/system/vk_builders.h"
#include "vulkan/system/vk_framebuffer.h"
#include "hw_shaderpatcher.h"
#include "filesystem.h"
#include "engineerrors.h"
@ -111,7 +113,7 @@ bool VkShaderManager::CompileNextShader()
return false;
}
VkShaderManager::VkShaderManager(VulkanDevice *device) : device(device)
VkShaderManager::VkShaderManager(VulkanFrameBuffer* fb) : fb(fb)
{
ShInitialize();
CompileNextShader();
@ -122,6 +124,12 @@ VkShaderManager::~VkShaderManager()
ShFinalize();
}
void VkShaderManager::Deinit()
{
while (!PPShaders.empty())
RemoveVkPPShader(PPShaders.back());
}
VkShaderProgram *VkShaderManager::GetEffect(int effect, EPassType passType)
{
if (compileIndex == -1 && effect >= 0 && effect < MAX_EFFECTS && mEffectShaders[passType][effect].frag)
@ -133,7 +141,8 @@ VkShaderProgram *VkShaderManager::GetEffect(int effect, EPassType passType)
VkShaderProgram *VkShaderManager::Get(unsigned int eff, bool alphateston, EPassType passType)
{
if (compileIndex != -1) return &mMaterialShaders[0][0];
if (compileIndex != -1)
return &mMaterialShaders[0][0];
// indices 0-2 match the warping modes, 3 no texture, the following are custom
if (!alphateston && eff < SHADER_NoTexture)
{
@ -148,8 +157,14 @@ VkShaderProgram *VkShaderManager::Get(unsigned int eff, bool alphateston, EPassT
static const char *shaderBindings = R"(
layout(set = 0, binding = 0) uniform sampler2D ShadowMap;
layout(set = 0, binding = 1) uniform sampler2DArray LightMap;
#ifdef SUPPORTS_RAYTRACING
layout(set = 0, binding = 2) uniform accelerationStructureEXT TopLevelAS;
#endif
// This must match the HWViewpointUniforms struct
layout(set = 0, binding = 0, std140) uniform ViewpointUBO {
layout(set = 1, binding = 0, std140) uniform ViewpointUBO {
mat4 ProjectionMatrix;
mat4 ViewMatrix;
mat4 NormalViewMatrix;
@ -165,13 +180,7 @@ static const char *shaderBindings = R"(
int uShadowmapFilter;
};
// light buffers
layout(set = 0, binding = 1, std430) buffer LightBufferSSO
{
vec4 lights[];
};
layout(set = 0, binding = 2, std140) uniform MatricesUBO {
layout(set = 1, binding = 1, std140) uniform MatricesUBO {
mat4 ModelMatrix;
mat4 NormalModelMatrix;
mat4 TextureMatrix;
@ -210,25 +219,28 @@ static const char *shaderBindings = R"(
vec4 padding1, padding2, padding3;
};
layout(set = 0, binding = 3, std140) uniform StreamUBO {
layout(set = 1, binding = 2, std140) uniform StreamUBO {
StreamData data[MAX_STREAM_DATA];
};
layout(set = 0, binding = 4) uniform sampler2D ShadowMap;
layout(set = 0, binding = 5) uniform sampler2DArray LightMap;
// light buffers
layout(set = 1, binding = 3, std430) buffer LightBufferSSO
{
vec4 lights[];
};
// textures
layout(set = 1, binding = 0) uniform sampler2D tex;
layout(set = 1, binding = 1) uniform sampler2D texture2;
layout(set = 1, binding = 2) uniform sampler2D texture3;
layout(set = 1, binding = 3) uniform sampler2D texture4;
layout(set = 1, binding = 4) uniform sampler2D texture5;
layout(set = 1, binding = 5) uniform sampler2D texture6;
layout(set = 1, binding = 6) uniform sampler2D texture7;
layout(set = 1, binding = 7) uniform sampler2D texture8;
layout(set = 1, binding = 8) uniform sampler2D texture9;
layout(set = 1, binding = 9) uniform sampler2D texture10;
layout(set = 1, binding = 10) uniform sampler2D texture11;
layout(set = 2, binding = 0) uniform sampler2D tex;
layout(set = 2, binding = 1) uniform sampler2D texture2;
layout(set = 2, binding = 2) uniform sampler2D texture3;
layout(set = 2, binding = 3) uniform sampler2D texture4;
layout(set = 2, binding = 4) uniform sampler2D texture5;
layout(set = 2, binding = 5) uniform sampler2D texture6;
layout(set = 2, binding = 6) uniform sampler2D texture7;
layout(set = 2, binding = 7) uniform sampler2D texture8;
layout(set = 2, binding = 8) uniform sampler2D texture9;
layout(set = 2, binding = 9) uniform sampler2D texture10;
layout(set = 2, binding = 10) uniform sampler2D texture11;
// This must match the PushConstants struct
layout(push_constant) uniform PushConstants
@ -325,18 +337,21 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadVertShader(FString shadername
code << "#define NPOT_EMULATION\n";
#endif
code << shaderBindings;
if (!device->UsedDeviceFeatures.shaderClipDistance) code << "#define NO_CLIPDISTANCE_SUPPORT\n";
if (!fb->device->UsedDeviceFeatures.shaderClipDistance) code << "#define NO_CLIPDISTANCE_SUPPORT\n";
code << "#line 1\n";
code << LoadPrivateShaderLump(vert_lump).GetChars() << "\n";
ShaderBuilder builder;
builder.setVertexShader(code);
return builder.create(shadername.GetChars(), device);
return ShaderBuilder()
.VertexShader(code)
.DebugName(shadername.GetChars())
.Create(shadername.GetChars(), fb->device);
}
std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername, const char *frag_lump, const char *material_lump, const char *light_lump, const char *defines, bool alphatest, bool gbufferpass)
{
FString code = GetTargetGlslVersion();
if (fb->RaytracingEnabled())
code << "\n#define SUPPORTS_RAYTRACING\n";
code << defines;
code << "\n$placeholder$"; // here the code can later add more needed #defines.
code << "\n#define MAX_STREAM_DATA " << std::to_string(MAX_STREAM_DATA).c_str() << "\n";
@ -346,7 +361,7 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername
code << shaderBindings;
FString placeholder = "\n";
if (!device->UsedDeviceFeatures.shaderClipDistance) code << "#define NO_CLIPDISTANCE_SUPPORT\n";
if (!fb->device->UsedDeviceFeatures.shaderClipDistance) code << "#define NO_CLIPDISTANCE_SUPPORT\n";
if (!alphatest) code << "#define NO_ALPHATEST\n";
if (gbufferpass) code << "#define GBUFFER_PASS\n";
@ -418,14 +433,22 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername
code << LoadPrivateShaderLump(light_lump).GetChars();
}
ShaderBuilder builder;
builder.setFragmentShader(code);
return builder.create(shadername.GetChars(), device);
return ShaderBuilder()
.FragmentShader(code)
.DebugName(shadername.GetChars())
.Create(shadername.GetChars(), fb->device);
}
FString VkShaderManager::GetTargetGlslVersion()
{
return "#version 450 core\n";
if (fb->device->ApiVersion == VK_API_VERSION_1_2)
{
return "#version 460\n#extension GL_EXT_ray_query : enable\n";
}
else
{
return "#version 450 core\n";
}
}
FString VkShaderManager::LoadPublicShaderLump(const char *lumpname)
@ -444,3 +467,22 @@ FString VkShaderManager::LoadPrivateShaderLump(const char *lumpname)
FileData data = fileSystem.ReadFile(lump);
return data.GetString();
}
VkPPShader* VkShaderManager::GetVkShader(PPShader* shader)
{
if (!shader->Backend)
shader->Backend = std::make_unique<VkPPShader>(fb, shader);
return static_cast<VkPPShader*>(shader->Backend.get());
}
void VkShaderManager::AddVkPPShader(VkPPShader* shader)
{
shader->it = PPShaders.insert(PPShaders.end(), shader);
}
void VkShaderManager::RemoveVkPPShader(VkPPShader* shader)
{
shader->Reset();
shader->fb = nullptr;
PPShaders.erase(shader->it);
}

View file

@ -7,11 +7,15 @@
#include "matrix.h"
#include "name.h"
#include "hw_renderstate.h"
#include <list>
#define SHADER_MIN_REQUIRED_TEXTURE_LAYERS 8
class VulkanFrameBuffer;
class VulkanDevice;
class VulkanShader;
class VkPPShader;
class PPShader;
struct MatricesUBO
{
@ -60,13 +64,20 @@ public:
class VkShaderManager
{
public:
VkShaderManager(VulkanDevice *device);
VkShaderManager(VulkanFrameBuffer* fb);
~VkShaderManager();
void Deinit();
VkShaderProgram *GetEffect(int effect, EPassType passType);
VkShaderProgram *Get(unsigned int eff, bool alphateston, EPassType passType);
bool CompileNextShader();
VkPPShader* GetVkShader(PPShader* shader);
void AddVkPPShader(VkPPShader* shader);
void RemoveVkPPShader(VkPPShader* shader);
private:
std::unique_ptr<VulkanShader> LoadVertShader(FString shadername, const char *vert_lump, const char *defines);
std::unique_ptr<VulkanShader> LoadFragShader(FString shadername, const char *frag_lump, const char *material_lump, const char *light_lump, const char *defines, bool alphatest, bool gbufferpass);
@ -75,11 +86,13 @@ private:
FString LoadPublicShaderLump(const char *lumpname);
FString LoadPrivateShaderLump(const char *lumpname);
VulkanDevice *device;
VulkanFrameBuffer* fb = nullptr;
std::vector<VkShaderProgram> mMaterialShaders[MAX_PASS_TYPES];
std::vector<VkShaderProgram> mMaterialShadersNAT[MAX_PASS_TYPES];
std::vector<VkShaderProgram> mEffectShaders[MAX_PASS_TYPES];
uint8_t compilePass = 0, compileState = 0;
int compileIndex = 0;
std::list<VkPPShader*> PPShaders;
};

View file

@ -0,0 +1,133 @@
/*
** Vulkan backend
** Copyright (c) 2016-2020 Magnus Norddahl
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
**
*/
#include "vk_buffer.h"
#include "vk_hwbuffer.h"
#include "vulkan/renderer/vk_streambuffer.h"
#include "hwrenderer/data/shaderuniforms.h"
VkBufferManager::VkBufferManager(VulkanFrameBuffer* fb) : fb(fb)
{
}
VkBufferManager::~VkBufferManager()
{
}
void VkBufferManager::Init()
{
MatrixBuffer.reset(new VkStreamBuffer(this, sizeof(MatricesUBO), 50000));
StreamBuffer.reset(new VkStreamBuffer(this, sizeof(StreamUBO), 300));
CreateFanToTrisIndexBuffer();
}
void VkBufferManager::Deinit()
{
while (!Buffers.empty())
RemoveBuffer(Buffers.back());
}
void VkBufferManager::AddBuffer(VkHardwareBuffer* buffer)
{
buffer->it = Buffers.insert(Buffers.end(), buffer);
}
void VkBufferManager::RemoveBuffer(VkHardwareBuffer* buffer)
{
buffer->Reset();
buffer->fb = nullptr;
Buffers.erase(buffer->it);
for (VkHardwareDataBuffer** knownbuf : { &ViewpointUBO, &LightBufferSSO, &LightNodes, &LightLines, &LightList })
{
if (buffer == *knownbuf) *knownbuf = nullptr;
}
}
IVertexBuffer* VkBufferManager::CreateVertexBuffer()
{
return new VkHardwareVertexBuffer(fb);
}
IIndexBuffer* VkBufferManager::CreateIndexBuffer()
{
return new VkHardwareIndexBuffer(fb);
}
IDataBuffer* VkBufferManager::CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize)
{
auto buffer = new VkHardwareDataBuffer(fb, bindingpoint, ssbo, needsresize);
switch (bindingpoint)
{
case LIGHTBUF_BINDINGPOINT: LightBufferSSO = buffer; break;
case VIEWPOINT_BINDINGPOINT: ViewpointUBO = buffer; break;
case LIGHTNODES_BINDINGPOINT: LightNodes = buffer; break;
case LIGHTLINES_BINDINGPOINT: LightLines = buffer; break;
case LIGHTLIST_BINDINGPOINT: LightList = buffer; break;
case POSTPROCESS_BINDINGPOINT: break;
default: break;
}
return buffer;
}
void VkBufferManager::CreateFanToTrisIndexBuffer()
{
TArray<uint32_t> data;
for (int i = 2; i < 1000; i++)
{
data.Push(0);
data.Push(i - 1);
data.Push(i);
}
FanToTrisIndexBuffer.reset(CreateIndexBuffer());
FanToTrisIndexBuffer->SetData(sizeof(uint32_t) * data.Size(), data.Data(), BufferUsageType::Static);
}
/////////////////////////////////////////////////////////////////////////////
VkStreamBuffer::VkStreamBuffer(VkBufferManager* buffers, size_t structSize, size_t count)
{
mBlockSize = static_cast<uint32_t>((structSize + screen->uniformblockalignment - 1) / screen->uniformblockalignment * screen->uniformblockalignment);
UniformBuffer = (VkHardwareDataBuffer*)buffers->CreateDataBuffer(-1, false, false);
UniformBuffer->SetData(mBlockSize * count, nullptr, BufferUsageType::Persistent);
}
VkStreamBuffer::~VkStreamBuffer()
{
delete UniformBuffer;
}
uint32_t VkStreamBuffer::NextStreamDataBlock()
{
mStreamDataOffset += mBlockSize;
if (mStreamDataOffset + (size_t)mBlockSize >= UniformBuffer->Size())
{
mStreamDataOffset = 0;
return 0xffffffff;
}
return mStreamDataOffset;
}

View file

@ -0,0 +1,64 @@
#pragma once
#include "vulkan/system/vk_objects.h"
#include <list>
class VulkanFrameBuffer;
class VkHardwareBuffer;
class VkHardwareDataBuffer;
class VkStreamBuffer;
class IIndexBuffer;
class IVertexBuffer;
class IDataBuffer;
class VkBufferManager
{
public:
VkBufferManager(VulkanFrameBuffer* fb);
~VkBufferManager();
void Init();
void Deinit();
IVertexBuffer* CreateVertexBuffer();
IIndexBuffer* CreateIndexBuffer();
IDataBuffer* CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize);
void AddBuffer(VkHardwareBuffer* buffer);
void RemoveBuffer(VkHardwareBuffer* buffer);
VkHardwareDataBuffer* ViewpointUBO = nullptr;
VkHardwareDataBuffer* LightBufferSSO = nullptr;
VkHardwareDataBuffer* LightNodes = nullptr;
VkHardwareDataBuffer* LightLines = nullptr;
VkHardwareDataBuffer* LightList = nullptr;
std::unique_ptr<VkStreamBuffer> MatrixBuffer;
std::unique_ptr<VkStreamBuffer> StreamBuffer;
std::unique_ptr<IIndexBuffer> FanToTrisIndexBuffer;
private:
void CreateFanToTrisIndexBuffer();
VulkanFrameBuffer* fb = nullptr;
std::list<VkHardwareBuffer*> Buffers;
};
class VkStreamBuffer
{
public:
VkStreamBuffer(VkBufferManager* buffers, size_t structSize, size_t count);
~VkStreamBuffer();
uint32_t NextStreamDataBlock();
void Reset() { mStreamDataOffset = 0; }
VkHardwareDataBuffer* UniformBuffer = nullptr;
private:
uint32_t mBlockSize = 0;
uint32_t mStreamDataOffset = 0;
};

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more