Parser: Implement extension GL_AMD_gpu_shader_half_float.
- Add built-in types: float16_t, f16vec, f16mat. - Add support of half float constant: hf, HF. - Extend built-in floating-point operators: +, -, *, /, ++, --, +=, -=, *=, /=, ==, !=, >=, <=, >, <. - Add support of type conversions: float16_t -> XXX, XXX -> float16_t. - Add new built-in functions.
This commit is contained in:
@@ -11,10 +11,12 @@ set(SPVREMAP_SOURCES
|
||||
doc.cpp)
|
||||
|
||||
set(HEADERS
|
||||
bitutils.h
|
||||
spirv.hpp
|
||||
GLSL.std.450.h
|
||||
GLSL.ext.KHR.h
|
||||
GlslangToSpv.h
|
||||
hex_float.h
|
||||
Logger.h
|
||||
SpvBuilder.h
|
||||
spvIR.h
|
||||
@@ -26,8 +28,9 @@ set(SPVREMAP_HEADERS
|
||||
doc.h)
|
||||
|
||||
if(ENABLE_AMD_EXTENSIONS)
|
||||
set(HEADERS
|
||||
GLSL.ext.AMD.h)
|
||||
list(APPEND
|
||||
HEADERS
|
||||
GLSL.ext.AMD.h)
|
||||
endif(ENABLE_AMD_EXTENSIONS)
|
||||
|
||||
add_library(SPIRV STATIC ${SOURCES} ${HEADERS})
|
||||
|
||||
@@ -32,7 +32,7 @@ enum Decoration;
|
||||
enum Op;
|
||||
|
||||
static const int GLSLextAMDVersion = 100;
|
||||
static const int GLSLextAMDRevision = 1;
|
||||
static const int GLSLextAMDRevision = 2;
|
||||
|
||||
// SPV_AMD_shader_ballot
|
||||
static const char* const E_SPV_AMD_shader_ballot = "SPV_AMD_shader_ballot";
|
||||
@@ -110,4 +110,7 @@ enum GcnShaderAMD {
|
||||
GcnShaderCountAMD
|
||||
};
|
||||
|
||||
// SPV_AMD_gpu_shader_half_float
|
||||
static const char* const E_SPV_AMD_gpu_shader_half_float = "SPV_AMD_gpu_shader_half_float";
|
||||
|
||||
#endif // #ifndef GLSLextAMD_H
|
||||
|
||||
@@ -1215,6 +1215,10 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
|
||||
one = builder.makeFloatConstant(1.0F);
|
||||
else if (node->getBasicType() == glslang::EbtDouble)
|
||||
one = builder.makeDoubleConstant(1.0);
|
||||
#ifdef AMD_EXTENSIONS
|
||||
else if (node->getBasicType() == glslang::EbtFloat16)
|
||||
one = builder.makeFloat16Constant(1.0F);
|
||||
#endif
|
||||
else if (node->getBasicType() == glslang::EbtInt64 || node->getBasicType() == glslang::EbtUint64)
|
||||
one = builder.makeInt64Constant(1);
|
||||
else
|
||||
@@ -1388,6 +1392,17 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
||||
case glslang::EOpConstructDMat4x2:
|
||||
case glslang::EOpConstructDMat4x3:
|
||||
case glslang::EOpConstructDMat4x4:
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EOpConstructF16Mat2x2:
|
||||
case glslang::EOpConstructF16Mat2x3:
|
||||
case glslang::EOpConstructF16Mat2x4:
|
||||
case glslang::EOpConstructF16Mat3x2:
|
||||
case glslang::EOpConstructF16Mat3x3:
|
||||
case glslang::EOpConstructF16Mat3x4:
|
||||
case glslang::EOpConstructF16Mat4x2:
|
||||
case glslang::EOpConstructF16Mat4x3:
|
||||
case glslang::EOpConstructF16Mat4x4:
|
||||
#endif
|
||||
isMatrix = true;
|
||||
// fall through
|
||||
case glslang::EOpConstructFloat:
|
||||
@@ -1398,6 +1413,12 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
||||
case glslang::EOpConstructDVec2:
|
||||
case glslang::EOpConstructDVec3:
|
||||
case glslang::EOpConstructDVec4:
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EOpConstructFloat16:
|
||||
case glslang::EOpConstructF16Vec2:
|
||||
case glslang::EOpConstructF16Vec3:
|
||||
case glslang::EOpConstructF16Vec4:
|
||||
#endif
|
||||
case glslang::EOpConstructBool:
|
||||
case glslang::EOpConstructBVec2:
|
||||
case glslang::EOpConstructBVec3:
|
||||
@@ -1901,7 +1922,6 @@ spv::Id TGlslangToSpvTraverser::createInvertedSwizzle(spv::Decoration precision,
|
||||
return builder.createRvalueSwizzle(precision, convertGlslangToSpvType(node.getType()), parentResult, swizzle);
|
||||
}
|
||||
|
||||
|
||||
// Convert a glslang AST swizzle node to a swizzle vector for building SPIR-V.
|
||||
void TGlslangToSpvTraverser::convertSwizzle(const glslang::TIntermAggregate& node, std::vector<unsigned>& swizzle)
|
||||
{
|
||||
@@ -1936,6 +1956,13 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
||||
case glslang::EbtDouble:
|
||||
spvType = builder.makeFloatType(64);
|
||||
break;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EbtFloat16:
|
||||
builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float);
|
||||
builder.addCapability(spv::CapabilityFloat16);
|
||||
spvType = builder.makeFloatType(16);
|
||||
break;
|
||||
#endif
|
||||
case glslang::EbtBool:
|
||||
// "transparent" bool doesn't exist in SPIR-V. The GLSL convention is
|
||||
// a 32-bit int where non-0 means true.
|
||||
@@ -3040,7 +3067,11 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv
|
||||
glslang::TBasicType typeProxy, bool reduceComparison)
|
||||
{
|
||||
bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble || typeProxy == glslang::EbtFloat16;
|
||||
#else
|
||||
bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble;
|
||||
#endif
|
||||
bool isBool = typeProxy == glslang::EbtBool;
|
||||
|
||||
spv::Op binOp = spv::OpNop;
|
||||
@@ -3366,7 +3397,11 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv:
|
||||
int extBuiltins = -1;
|
||||
int libCall = -1;
|
||||
bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble || typeProxy == glslang::EbtFloat16;
|
||||
#else
|
||||
bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble;
|
||||
#endif
|
||||
|
||||
switch (op) {
|
||||
case glslang::EOpNegative:
|
||||
@@ -3550,6 +3585,13 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv:
|
||||
unaryOp = spv::OpBitcast;
|
||||
break;
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EOpPackFloat2x16:
|
||||
case glslang::EOpUnpackFloat2x16:
|
||||
unaryOp = spv::OpBitcast;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case glslang::EOpDPdx:
|
||||
unaryOp = spv::OpDPdx;
|
||||
break;
|
||||
@@ -3746,22 +3788,40 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, spv::Dec
|
||||
zero = makeSmearedConstant(zero, vectorSize);
|
||||
return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero);
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EOpConvFloat16ToBool:
|
||||
zero = builder.makeFloat16Constant(0.0F);
|
||||
zero = makeSmearedConstant(zero, vectorSize);
|
||||
return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero);
|
||||
#endif
|
||||
|
||||
case glslang::EOpConvBoolToFloat:
|
||||
convOp = spv::OpSelect;
|
||||
zero = builder.makeFloatConstant(0.0);
|
||||
one = builder.makeFloatConstant(1.0);
|
||||
zero = builder.makeFloatConstant(0.0F);
|
||||
one = builder.makeFloatConstant(1.0F);
|
||||
break;
|
||||
|
||||
case glslang::EOpConvBoolToDouble:
|
||||
convOp = spv::OpSelect;
|
||||
zero = builder.makeDoubleConstant(0.0);
|
||||
one = builder.makeDoubleConstant(1.0);
|
||||
break;
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EOpConvBoolToFloat16:
|
||||
convOp = spv::OpSelect;
|
||||
zero = builder.makeFloat16Constant(0.0F);
|
||||
one = builder.makeFloat16Constant(1.0F);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case glslang::EOpConvBoolToInt:
|
||||
case glslang::EOpConvBoolToInt64:
|
||||
zero = (op == glslang::EOpConvBoolToInt64) ? builder.makeInt64Constant(0) : builder.makeIntConstant(0);
|
||||
one = (op == glslang::EOpConvBoolToInt64) ? builder.makeInt64Constant(1) : builder.makeIntConstant(1);
|
||||
convOp = spv::OpSelect;
|
||||
break;
|
||||
|
||||
case glslang::EOpConvBoolToUint:
|
||||
case glslang::EOpConvBoolToUint64:
|
||||
zero = (op == glslang::EOpConvBoolToUint64) ? builder.makeUint64Constant(0) : builder.makeUintConstant(0);
|
||||
@@ -3773,6 +3833,10 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, spv::Dec
|
||||
case glslang::EOpConvIntToDouble:
|
||||
case glslang::EOpConvInt64ToFloat:
|
||||
case glslang::EOpConvInt64ToDouble:
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EOpConvIntToFloat16:
|
||||
case glslang::EOpConvInt64ToFloat16:
|
||||
#endif
|
||||
convOp = spv::OpConvertSToF;
|
||||
break;
|
||||
|
||||
@@ -3780,11 +3844,21 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, spv::Dec
|
||||
case glslang::EOpConvUintToDouble:
|
||||
case glslang::EOpConvUint64ToFloat:
|
||||
case glslang::EOpConvUint64ToDouble:
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EOpConvUintToFloat16:
|
||||
case glslang::EOpConvUint64ToFloat16:
|
||||
#endif
|
||||
convOp = spv::OpConvertUToF;
|
||||
break;
|
||||
|
||||
case glslang::EOpConvDoubleToFloat:
|
||||
case glslang::EOpConvFloatToDouble:
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EOpConvDoubleToFloat16:
|
||||
case glslang::EOpConvFloat16ToDouble:
|
||||
case glslang::EOpConvFloatToFloat16:
|
||||
case glslang::EOpConvFloat16ToFloat:
|
||||
#endif
|
||||
convOp = spv::OpFConvert;
|
||||
if (builder.isMatrixType(destType))
|
||||
return createUnaryMatrixOperation(convOp, precision, noContraction, destType, operand, typeProxy);
|
||||
@@ -3794,6 +3868,10 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, spv::Dec
|
||||
case glslang::EOpConvDoubleToInt:
|
||||
case glslang::EOpConvFloatToInt64:
|
||||
case glslang::EOpConvDoubleToInt64:
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EOpConvFloat16ToInt:
|
||||
case glslang::EOpConvFloat16ToInt64:
|
||||
#endif
|
||||
convOp = spv::OpConvertFToS;
|
||||
break;
|
||||
|
||||
@@ -3818,6 +3896,10 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, spv::Dec
|
||||
case glslang::EOpConvDoubleToUint:
|
||||
case glslang::EOpConvFloatToUint64:
|
||||
case glslang::EOpConvDoubleToUint64:
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EOpConvFloat16ToUint:
|
||||
case glslang::EOpConvFloat16ToUint64:
|
||||
#endif
|
||||
convOp = spv::OpConvertFToU;
|
||||
break;
|
||||
|
||||
@@ -3987,7 +4069,11 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
|
||||
spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
|
||||
{
|
||||
bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble || typeProxy == glslang::EbtFloat16;
|
||||
#else
|
||||
bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble;
|
||||
#endif
|
||||
|
||||
spv::Op opCode = spv::OpNop;
|
||||
|
||||
@@ -4185,7 +4271,11 @@ spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv
|
||||
spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
|
||||
{
|
||||
bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble || typeProxy == glslang::EbtFloat16;
|
||||
#else
|
||||
bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble;
|
||||
#endif
|
||||
|
||||
spv::Op opCode = spv::OpNop;
|
||||
int extBuiltins = -1;
|
||||
@@ -4715,6 +4805,11 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla
|
||||
case glslang::EbtDouble:
|
||||
spvConsts.push_back(builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst()));
|
||||
break;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EbtFloat16:
|
||||
spvConsts.push_back(builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst()));
|
||||
break;
|
||||
#endif
|
||||
case glslang::EbtBool:
|
||||
spvConsts.push_back(builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst()));
|
||||
break;
|
||||
@@ -4747,6 +4842,11 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla
|
||||
case glslang::EbtDouble:
|
||||
scalar = builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst(), specConstant);
|
||||
break;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EbtFloat16:
|
||||
scalar = builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant);
|
||||
break;
|
||||
#endif
|
||||
case glslang::EbtBool:
|
||||
scalar = builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst(), specConstant);
|
||||
break;
|
||||
|
||||
@@ -46,6 +46,10 @@
|
||||
|
||||
#include "SpvBuilder.h"
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
#include "hex_float.h"
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <cstdio>
|
||||
#endif
|
||||
@@ -785,6 +789,36 @@ Id Builder::makeDoubleConstant(double d, bool specConstant)
|
||||
return c->getResultId();
|
||||
}
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
Id Builder::makeFloat16Constant(float f16, bool specConstant)
|
||||
{
|
||||
Op opcode = specConstant ? OpSpecConstant : OpConstant;
|
||||
Id typeId = makeFloatType(16);
|
||||
|
||||
spvutils::HexFloat<spvutils::FloatProxy<float>> fVal(f16);
|
||||
spvutils::HexFloat<spvutils::FloatProxy<spvutils::Float16>> f16Val(0);
|
||||
fVal.castTo(f16Val, spvutils::round_direction::kToZero);
|
||||
|
||||
unsigned value = f16Val.value().getAsFloat().get_value();
|
||||
|
||||
// See if we already made it. Applies only to regular constants, because specialization constants
|
||||
// must remain distinct for the purpose of applying a SpecId decoration.
|
||||
if (!specConstant) {
|
||||
Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, value);
|
||||
if (existing)
|
||||
return existing;
|
||||
}
|
||||
|
||||
Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
|
||||
c->addImmediateOperand(value);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
|
||||
groupedConstants[OpTypeFloat].push_back(c);
|
||||
module.mapInstruction(c);
|
||||
|
||||
return c->getResultId();
|
||||
}
|
||||
#endif
|
||||
|
||||
Id Builder::findCompositeConstant(Op typeClass, std::vector<Id>& comps) const
|
||||
{
|
||||
Instruction* constant = 0;
|
||||
|
||||
@@ -191,6 +191,9 @@ public:
|
||||
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);
|
||||
#ifdef AMD_EXTENSIONS
|
||||
Id makeFloat16Constant(float f16, bool specConstant = false);
|
||||
#endif
|
||||
|
||||
// Turn the array of constants into a proper spv constant of the requested type.
|
||||
Id makeCompositeConstant(Id type, std::vector<Id>& comps, bool specConst = false);
|
||||
|
||||
81
SPIRV/bitutils.h
Normal file
81
SPIRV/bitutils.h
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_UTIL_BITUTILS_H_
|
||||
#define LIBSPIRV_UTIL_BITUTILS_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
namespace spvutils {
|
||||
|
||||
// Performs a bitwise copy of source to the destination type Dest.
|
||||
template <typename Dest, typename Src>
|
||||
Dest BitwiseCast(Src source) {
|
||||
Dest dest;
|
||||
static_assert(sizeof(source) == sizeof(dest),
|
||||
"BitwiseCast: Source and destination must have the same size");
|
||||
std::memcpy(&dest, &source, sizeof(dest));
|
||||
return dest;
|
||||
}
|
||||
|
||||
// SetBits<T, First, Num> returns an integer of type <T> with bits set
|
||||
// for position <First> through <First + Num - 1>, counting from the least
|
||||
// significant bit. In particular when Num == 0, no positions are set to 1.
|
||||
// A static assert will be triggered if First + Num > sizeof(T) * 8, that is,
|
||||
// a bit that will not fit in the underlying type is set.
|
||||
template <typename T, size_t First = 0, size_t Num = 0>
|
||||
struct SetBits {
|
||||
static_assert(First < sizeof(T) * 8,
|
||||
"Tried to set a bit that is shifted too far.");
|
||||
const static T get = (T(1) << First) | SetBits<T, First + 1, Num - 1>::get;
|
||||
};
|
||||
|
||||
template <typename T, size_t Last>
|
||||
struct SetBits<T, Last, 0> {
|
||||
const static T get = T(0);
|
||||
};
|
||||
|
||||
// This is all compile-time so we can put our tests right here.
|
||||
static_assert(SetBits<uint32_t, 0, 0>::get == uint32_t(0x00000000),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 0, 1>::get == uint32_t(0x00000001),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 31, 1>::get == uint32_t(0x80000000),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 1, 2>::get == uint32_t(0x00000006),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 30, 2>::get == uint32_t(0xc0000000),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 0, 31>::get == uint32_t(0x7FFFFFFF),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 0, 32>::get == uint32_t(0xFFFFFFFF),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 16, 16>::get == uint32_t(0xFFFF0000),
|
||||
"SetBits failed");
|
||||
|
||||
static_assert(SetBits<uint64_t, 0, 1>::get == uint64_t(0x0000000000000001LL),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint64_t, 63, 1>::get == uint64_t(0x8000000000000000LL),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint64_t, 62, 2>::get == uint64_t(0xc000000000000000LL),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint64_t, 31, 1>::get == uint64_t(0x0000000080000000LL),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint64_t, 16, 16>::get == uint64_t(0x00000000FFFF0000LL),
|
||||
"SetBits failed");
|
||||
|
||||
} // namespace spvutils
|
||||
|
||||
#endif // LIBSPIRV_UTIL_BITUTILS_H_
|
||||
1076
SPIRV/hex_float.h
Normal file
1076
SPIRV/hex_float.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user