Begin adding float16_t support to GLSL.
This commit is contained in:
Родитель
b0a2de5b63
Коммит
91f85d3412
|
@ -263,6 +263,7 @@ struct SPIRType : IVariant
|
|||
Int64,
|
||||
UInt64,
|
||||
AtomicCounter,
|
||||
Half,
|
||||
Float,
|
||||
Double,
|
||||
Struct,
|
||||
|
@ -751,6 +752,58 @@ struct SPIRConstant : IVariant
|
|||
}
|
||||
};
|
||||
|
||||
static inline float f16_to_f32(uint16_t u16_value)
|
||||
{
|
||||
// Based on the GLM implementation.
|
||||
int s = (u16_value >> 15) & 0x1;
|
||||
int e = (u16_value >> 10) & 0x1f;
|
||||
int m = (u16_value >> 0) & 0x3ff;
|
||||
|
||||
union
|
||||
{
|
||||
float f32;
|
||||
uint32_t u32;
|
||||
} u;
|
||||
|
||||
if (e == 0)
|
||||
{
|
||||
if (m == 0)
|
||||
{
|
||||
u.u32 = uint32_t(s) << 31;
|
||||
return u.f32;
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((m & 0x400) == 0)
|
||||
{
|
||||
m <<= 1;
|
||||
e--;
|
||||
}
|
||||
|
||||
e++;
|
||||
m &= ~0x400;
|
||||
}
|
||||
}
|
||||
else if (e == 31)
|
||||
{
|
||||
if (m == 0)
|
||||
{
|
||||
u.u32 = (uint32_t(s) << 31) | 0x7f800000u;
|
||||
return u.f32;
|
||||
}
|
||||
else
|
||||
{
|
||||
u.u32 = (uint32_t(s) << 31) | 0x7f800000u | (m << 13);
|
||||
return u.f32;
|
||||
}
|
||||
}
|
||||
|
||||
e += 127 - 15;
|
||||
m <<= 13;
|
||||
u.u32 = (uint32_t(s) << 31) | (e << 23) | m;
|
||||
return u.f32;
|
||||
}
|
||||
|
||||
inline uint32_t specialization_constant_id(uint32_t col, uint32_t row) const
|
||||
{
|
||||
return m.c[col].id[row];
|
||||
|
@ -766,6 +819,16 @@ struct SPIRConstant : IVariant
|
|||
return m.c[col].r[row].u32;
|
||||
}
|
||||
|
||||
inline uint16_t scalar_u16(uint32_t col = 0, uint32_t row = 0) const
|
||||
{
|
||||
return uint16_t(m.c[col].r[row].u32 & 0xffffu);
|
||||
}
|
||||
|
||||
inline float scalar_f16(uint32_t col = 0, uint32_t row = 0) const
|
||||
{
|
||||
return f16_to_f32(scalar_u16(col, row));
|
||||
}
|
||||
|
||||
inline float scalar_f32(uint32_t col = 0, uint32_t row = 0) const
|
||||
{
|
||||
return m.c[col].r[row].f32;
|
||||
|
|
|
@ -1565,7 +1565,14 @@ void Compiler::parse(const Instruction &instruction)
|
|||
uint32_t id = ops[0];
|
||||
uint32_t width = ops[1];
|
||||
auto &type = set<SPIRType>(id);
|
||||
type.basetype = width > 32 ? SPIRType::Double : SPIRType::Float;
|
||||
if (width == 64)
|
||||
type.basetype = SPIRType::Double;
|
||||
else if (width == 32)
|
||||
type.basetype = SPIRType::Float;
|
||||
else if (width == 16)
|
||||
type.basetype = SPIRType::Half;
|
||||
else
|
||||
SPIRV_CROSS_THROW("Unrecognized bit-width of floating point type.");
|
||||
type.width = width;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,13 @@ using namespace spv;
|
|||
using namespace spirv_cross;
|
||||
using namespace std;
|
||||
|
||||
static bool type_is_floating_point(const SPIRType &type)
|
||||
{
|
||||
return type.basetype == SPIRType::Half ||
|
||||
type.basetype == SPIRType::Float ||
|
||||
type.basetype == SPIRType::Double;
|
||||
}
|
||||
|
||||
static bool packing_is_vec4_padded(BufferPackingStandard packing)
|
||||
{
|
||||
switch (packing)
|
||||
|
@ -319,6 +326,9 @@ void CompilerGLSL::find_static_extensions()
|
|||
if (!options.es)
|
||||
require_extension("GL_ARB_gpu_shader_int64");
|
||||
}
|
||||
|
||||
if (type.basetype == SPIRType::Half)
|
||||
require_extension("GL_AMD_gpu_shader_half_float");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2567,6 +2577,29 @@ string CompilerGLSL::constant_expression(const SPIRConstant &c)
|
|||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
string CompilerGLSL::convert_half_to_string(const SPIRConstant &c, uint32_t col, uint32_t row)
|
||||
{
|
||||
string res;
|
||||
float float_value = c.scalar_f16(col, row);
|
||||
|
||||
if (std::isnan(float_value) || std::isinf(float_value))
|
||||
{
|
||||
// There is no uintBitsToFloat for 16-bit, so have to rely on legacy fallback here.
|
||||
if (float_value == numeric_limits<float>::infinity())
|
||||
res = "(1.0hf / 0.0hf)";
|
||||
else if (float_value == -numeric_limits<float>::infinity())
|
||||
res = "(-1.0hf / 0.0hf)";
|
||||
else if (std::isnan(float_value))
|
||||
res = "(0.0hf / 0.0hf)";
|
||||
else
|
||||
SPIRV_CROSS_THROW("Cannot represent non-finite floating point constant.");
|
||||
}
|
||||
else
|
||||
res = convert_to_string(float_value) + "hf";
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
string CompilerGLSL::convert_float_to_string(const SPIRConstant &c, uint32_t col, uint32_t row)
|
||||
{
|
||||
string res;
|
||||
|
@ -2712,7 +2745,7 @@ string CompilerGLSL::constant_expression_vector(const SPIRConstant &c, uint32_t
|
|||
bool splat = backend.use_constructor_splatting && c.vector_size() > 1;
|
||||
bool swizzle_splat = backend.can_swizzle_scalar && c.vector_size() > 1;
|
||||
|
||||
if (type.basetype != SPIRType::Float && type.basetype != SPIRType::Double)
|
||||
if (!type_is_floating_point(type))
|
||||
{
|
||||
// Cannot swizzle literal integers as a special case.
|
||||
swizzle_splat = false;
|
||||
|
@ -2766,6 +2799,28 @@ string CompilerGLSL::constant_expression_vector(const SPIRConstant &c, uint32_t
|
|||
|
||||
switch (type.basetype)
|
||||
{
|
||||
case SPIRType::Half:
|
||||
if (splat || swizzle_splat)
|
||||
{
|
||||
res += convert_half_to_string(c, vector, 0);
|
||||
if (swizzle_splat)
|
||||
res = remap_swizzle(get<SPIRType>(c.constant_type), 1, res);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t i = 0; i < c.vector_size(); i++)
|
||||
{
|
||||
if (options.vulkan_semantics && c.vector_size() > 1 && c.specialization_constant_id(vector, i) != 0)
|
||||
res += to_name(c.specialization_constant_id(vector, i));
|
||||
else
|
||||
res += convert_half_to_string(c, vector, i);
|
||||
|
||||
if (i + 1 < c.vector_size())
|
||||
res += ", ";
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SPIRType::Float:
|
||||
if (splat || swizzle_splat)
|
||||
{
|
||||
|
@ -3310,6 +3365,10 @@ bool CompilerGLSL::to_trivial_mix_op(const SPIRType &type, string &op, uint32_t
|
|||
ret = cleft->scalar() == 0 && cright->scalar() == 1;
|
||||
break;
|
||||
|
||||
case SPIRType::Half:
|
||||
ret = cleft->scalar_f16() == 0.0f && cright->scalar_f16() == 1.0f;
|
||||
break;
|
||||
|
||||
case SPIRType::Float:
|
||||
ret = cleft->scalar_f32() == 0.0f && cright->scalar_f32() == 1.0f;
|
||||
break;
|
||||
|
@ -5716,7 +5775,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
|||
bool swizzle_splat = in_type.vecsize == 1 && in_type.columns == 1 && backend.can_swizzle_scalar;
|
||||
|
||||
if (ids[elems[0]].get_type() == TypeConstant &&
|
||||
(in_type.basetype != SPIRType::Float && in_type.basetype != SPIRType::Double))
|
||||
!type_is_floating_point(in_type))
|
||||
{
|
||||
// Cannot swizzle literal integers as a special case.
|
||||
swizzle_splat = false;
|
||||
|
@ -7724,6 +7783,8 @@ string CompilerGLSL::type_to_glsl(const SPIRType &type, uint32_t id)
|
|||
return backend.basic_uint_type;
|
||||
case SPIRType::AtomicCounter:
|
||||
return "atomic_uint";
|
||||
case SPIRType::Half:
|
||||
return "float16_t";
|
||||
case SPIRType::Float:
|
||||
return "float";
|
||||
case SPIRType::Double:
|
||||
|
@ -7746,6 +7807,8 @@ string CompilerGLSL::type_to_glsl(const SPIRType &type, uint32_t id)
|
|||
return join("ivec", type.vecsize);
|
||||
case SPIRType::UInt:
|
||||
return join("uvec", type.vecsize);
|
||||
case SPIRType::Half:
|
||||
return join("f16vec", type.vecsize);
|
||||
case SPIRType::Float:
|
||||
return join("vec", type.vecsize);
|
||||
case SPIRType::Double:
|
||||
|
@ -7768,6 +7831,8 @@ string CompilerGLSL::type_to_glsl(const SPIRType &type, uint32_t id)
|
|||
return join("imat", type.vecsize);
|
||||
case SPIRType::UInt:
|
||||
return join("umat", type.vecsize);
|
||||
case SPIRType::Half:
|
||||
return join("f16mat", type.vecsize);
|
||||
case SPIRType::Float:
|
||||
return join("mat", type.vecsize);
|
||||
case SPIRType::Double:
|
||||
|
@ -7787,6 +7852,8 @@ string CompilerGLSL::type_to_glsl(const SPIRType &type, uint32_t id)
|
|||
return join("imat", type.columns, "x", type.vecsize);
|
||||
case SPIRType::UInt:
|
||||
return join("umat", type.columns, "x", type.vecsize);
|
||||
case SPIRType::Half:
|
||||
return join("f16mat", type.columns, "x", type.vecsize);
|
||||
case SPIRType::Float:
|
||||
return join("mat", type.columns, "x", type.vecsize);
|
||||
case SPIRType::Double:
|
||||
|
|
|
@ -528,6 +528,7 @@ protected:
|
|||
const Instruction *get_next_instruction_in_block(const Instruction &instr);
|
||||
static uint32_t mask_relevant_memory_semantics(uint32_t semantics);
|
||||
|
||||
std::string convert_half_to_string(const SPIRConstant &value, uint32_t col, uint32_t row);
|
||||
std::string convert_float_to_string(const SPIRConstant &value, uint32_t col, uint32_t row);
|
||||
std::string convert_double_to_string(const SPIRConstant &value, uint32_t col, uint32_t row);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче