GLSL/MSL: Implement 8-bit part of VK_KHR_shader_float16_int8.
Storage was in place already, so mostly just dealing with bitcasts and constants. Simplies some of the bitcasting logic, and this exposed some bugs in the implementation. Refactor to use correct width integers with explicit bitcast opcodes.
This commit is contained in:
parent
2edee351f0
commit
2ed171e525
77
reference/opt/shaders-msl/frag/shader-arithmetic-8bit.frag
Normal file
77
reference/opt/shaders-msl/frag/shader-arithmetic-8bit.frag
Normal file
@ -0,0 +1,77 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct SSBO
|
||||
{
|
||||
char i8[16];
|
||||
uchar u8[16];
|
||||
};
|
||||
|
||||
struct Push
|
||||
{
|
||||
char i8;
|
||||
uchar u8;
|
||||
};
|
||||
|
||||
struct UBO
|
||||
{
|
||||
char i8;
|
||||
uchar u8;
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
int4 FragColorInt [[color(0)]];
|
||||
uint4 FragColorUint [[color(1)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
int4 vColor [[user(locn0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], constant Push& registers [[buffer(0)]], constant UBO& ubo [[buffer(0)]], device SSBO& ssbo [[buffer(1)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
short _196 = 10;
|
||||
int _197 = 20;
|
||||
char2 _198 = as_type<char2>(_196);
|
||||
char4 _199 = as_type<char4>(_197);
|
||||
_196 = as_type<short>(_198);
|
||||
_197 = as_type<int>(_199);
|
||||
ssbo.i8[0] = _199.x;
|
||||
ssbo.i8[1] = _199.y;
|
||||
ssbo.i8[2] = _199.z;
|
||||
ssbo.i8[3] = _199.w;
|
||||
ushort _220 = 10u;
|
||||
uint _221 = 20u;
|
||||
uchar2 _222 = as_type<uchar2>(_220);
|
||||
uchar4 _223 = as_type<uchar4>(_221);
|
||||
_220 = as_type<ushort>(_222);
|
||||
_221 = as_type<uint>(_223);
|
||||
ssbo.u8[0] = _223.x;
|
||||
ssbo.u8[1] = _223.y;
|
||||
ssbo.u8[2] = _223.z;
|
||||
ssbo.u8[3] = _223.w;
|
||||
char4 _246 = char4(in.vColor);
|
||||
char4 _244 = _246;
|
||||
_244 += char4(registers.i8);
|
||||
_244 += char4(-40);
|
||||
_244 += char4(-50);
|
||||
_244 += char4(char(10), char(20), char(30), char(40));
|
||||
_244 += char4(ssbo.i8[4]);
|
||||
_244 += char4(ubo.i8);
|
||||
out.FragColorInt = int4(_244);
|
||||
uchar4 _271 = uchar4(_246);
|
||||
_271 += uchar4(registers.u8);
|
||||
_271 += uchar4(216);
|
||||
_271 += uchar4(206);
|
||||
_271 += uchar4(uchar(10), uchar(20), uchar(30), uchar(40));
|
||||
_271 += uchar4(ssbo.u8[4]);
|
||||
_271 += uchar4(ubo.u8);
|
||||
out.FragColorUint = uint4(_271);
|
||||
return out;
|
||||
}
|
||||
|
@ -3,15 +3,11 @@
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
#elif defined(GL_NV_gpu_shader5)
|
||||
#extension GL_NV_gpu_shader5 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for FP16.
|
||||
#endif
|
||||
#if defined(GL_AMD_gpu_shader_int16)
|
||||
#extension GL_AMD_gpu_shader_int16 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for Int16.
|
||||
#endif
|
||||
|
@ -1,8 +1,6 @@
|
||||
#version 450
|
||||
#if defined(GL_AMD_gpu_shader_int16)
|
||||
#extension GL_AMD_gpu_shader_int16 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for Int16.
|
||||
#endif
|
||||
@ -10,8 +8,6 @@
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
#elif defined(GL_NV_gpu_shader5)
|
||||
#extension GL_NV_gpu_shader5 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for FP16.
|
||||
#endif
|
||||
|
@ -3,8 +3,6 @@
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
#elif defined(GL_NV_gpu_shader5)
|
||||
#extension GL_NV_gpu_shader5 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for FP16.
|
||||
#endif
|
||||
|
@ -3,15 +3,11 @@
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
#elif defined(GL_NV_gpu_shader5)
|
||||
#extension GL_NV_gpu_shader5 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for FP16.
|
||||
#endif
|
||||
#if defined(GL_AMD_gpu_shader_int16)
|
||||
#extension GL_AMD_gpu_shader_int16 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for Int16.
|
||||
#endif
|
||||
|
@ -0,0 +1,69 @@
|
||||
#version 450
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require
|
||||
#extension GL_EXT_shader_8bit_storage : require
|
||||
|
||||
layout(set = 0, binding = 1, std430) buffer SSBO
|
||||
{
|
||||
int8_t i8[16];
|
||||
uint8_t u8[16];
|
||||
} ssbo;
|
||||
|
||||
layout(set = 0, binding = 0, std140) uniform UBO
|
||||
{
|
||||
int8_t i8;
|
||||
uint8_t u8;
|
||||
} ubo;
|
||||
|
||||
layout(push_constant, std430) uniform Push
|
||||
{
|
||||
int8_t i8;
|
||||
uint8_t u8;
|
||||
} registers;
|
||||
|
||||
layout(location = 0) flat in ivec4 vColor;
|
||||
layout(location = 0) out ivec4 FragColorInt;
|
||||
layout(location = 1) out uvec4 FragColorUint;
|
||||
|
||||
void main()
|
||||
{
|
||||
int16_t _196 = 10s;
|
||||
int _197 = 20;
|
||||
i8vec2 _198 = unpack8(_196);
|
||||
i8vec4 _199 = unpack8(_197);
|
||||
_196 = pack16(_198);
|
||||
_197 = pack32(_199);
|
||||
ssbo.i8[0] = _199.x;
|
||||
ssbo.i8[1] = _199.y;
|
||||
ssbo.i8[2] = _199.z;
|
||||
ssbo.i8[3] = _199.w;
|
||||
uint16_t _220 = 10us;
|
||||
uint _221 = 20u;
|
||||
u8vec2 _222 = unpack8(_220);
|
||||
u8vec4 _223 = unpack8(_221);
|
||||
_220 = pack16(_222);
|
||||
_221 = pack32(_223);
|
||||
ssbo.u8[0] = _223.x;
|
||||
ssbo.u8[1] = _223.y;
|
||||
ssbo.u8[2] = _223.z;
|
||||
ssbo.u8[3] = _223.w;
|
||||
i8vec4 _246 = i8vec4(vColor);
|
||||
i8vec4 _244 = _246;
|
||||
_244 += i8vec4(registers.i8);
|
||||
_244 += i8vec4(-40);
|
||||
_244 += i8vec4(-50);
|
||||
_244 += i8vec4(int8_t(10), int8_t(20), int8_t(30), int8_t(40));
|
||||
_244 += i8vec4(ssbo.i8[4]);
|
||||
_244 += i8vec4(ubo.i8);
|
||||
FragColorInt = ivec4(_244);
|
||||
u8vec4 _271 = u8vec4(_246);
|
||||
_271 += u8vec4(registers.u8);
|
||||
_271 += u8vec4(216);
|
||||
_271 += u8vec4(206);
|
||||
_271 += u8vec4(uint8_t(10), uint8_t(20), uint8_t(30), uint8_t(40));
|
||||
_271 += u8vec4(ssbo.u8[4]);
|
||||
_271 += u8vec4(ubo.u8);
|
||||
FragColorUint = uvec4(_271);
|
||||
}
|
||||
|
@ -1,18 +1,14 @@
|
||||
#version 450
|
||||
#if defined(GL_AMD_gpu_shader_int16)
|
||||
#extension GL_AMD_gpu_shader_int16 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for Int16.
|
||||
#endif
|
||||
#extension GL_EXT_shader_8bit_storage : require
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require
|
||||
#if defined(GL_AMD_gpu_shader_half_float)
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
#elif defined(GL_NV_gpu_shader5)
|
||||
#extension GL_NV_gpu_shader5 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for FP16.
|
||||
#endif
|
||||
|
@ -1,16 +1,12 @@
|
||||
#version 450
|
||||
#if defined(GL_AMD_gpu_shader_int16)
|
||||
#extension GL_AMD_gpu_shader_int16 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for Int16.
|
||||
#endif
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require
|
||||
#extension GL_EXT_shader_8bit_storage : require
|
||||
#if defined(GL_AMD_gpu_shader_half_float)
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#elif defined(GL_EXT_shader_explicit_arithmetic_types_float16)
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require
|
||||
#else
|
||||
#error No extension available for FP16.
|
||||
#endif
|
||||
|
98
reference/shaders-msl/frag/shader-arithmetic-8bit.frag
Normal file
98
reference/shaders-msl/frag/shader-arithmetic-8bit.frag
Normal file
@ -0,0 +1,98 @@
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct SSBO
|
||||
{
|
||||
char i8[16];
|
||||
uchar u8[16];
|
||||
};
|
||||
|
||||
struct Push
|
||||
{
|
||||
char i8;
|
||||
uchar u8;
|
||||
};
|
||||
|
||||
struct UBO
|
||||
{
|
||||
char i8;
|
||||
uchar u8;
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
int4 FragColorInt [[color(0)]];
|
||||
uint4 FragColorUint [[color(1)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
int4 vColor [[user(locn0)]];
|
||||
};
|
||||
|
||||
void packing_int8(device SSBO& ssbo)
|
||||
{
|
||||
short i16 = 10;
|
||||
int i32 = 20;
|
||||
char2 i8_2 = as_type<char2>(i16);
|
||||
char4 i8_4 = as_type<char4>(i32);
|
||||
i16 = as_type<short>(i8_2);
|
||||
i32 = as_type<int>(i8_4);
|
||||
ssbo.i8[0] = i8_4.x;
|
||||
ssbo.i8[1] = i8_4.y;
|
||||
ssbo.i8[2] = i8_4.z;
|
||||
ssbo.i8[3] = i8_4.w;
|
||||
}
|
||||
|
||||
void packing_uint8(device SSBO& ssbo)
|
||||
{
|
||||
ushort u16 = 10u;
|
||||
uint u32 = 20u;
|
||||
uchar2 u8_2 = as_type<uchar2>(u16);
|
||||
uchar4 u8_4 = as_type<uchar4>(u32);
|
||||
u16 = as_type<ushort>(u8_2);
|
||||
u32 = as_type<uint>(u8_4);
|
||||
ssbo.u8[0] = u8_4.x;
|
||||
ssbo.u8[1] = u8_4.y;
|
||||
ssbo.u8[2] = u8_4.z;
|
||||
ssbo.u8[3] = u8_4.w;
|
||||
}
|
||||
|
||||
void compute_int8(device SSBO& ssbo, thread int4& vColor, constant Push& registers, constant UBO& ubo, thread int4& FragColorInt)
|
||||
{
|
||||
char4 tmp = char4(vColor);
|
||||
tmp += char4(registers.i8);
|
||||
tmp += char4(char(-40));
|
||||
tmp += char4(-50);
|
||||
tmp += char4(char(10), char(20), char(30), char(40));
|
||||
tmp += char4(ssbo.i8[4]);
|
||||
tmp += char4(ubo.i8);
|
||||
FragColorInt = int4(tmp);
|
||||
}
|
||||
|
||||
void compute_uint8(device SSBO& ssbo, thread int4& vColor, constant Push& registers, constant UBO& ubo, thread uint4& FragColorUint)
|
||||
{
|
||||
uchar4 tmp = uchar4(char4(vColor));
|
||||
tmp += uchar4(registers.u8);
|
||||
tmp += uchar4(uchar(216));
|
||||
tmp += uchar4(206);
|
||||
tmp += uchar4(uchar(10), uchar(20), uchar(30), uchar(40));
|
||||
tmp += uchar4(ssbo.u8[4]);
|
||||
tmp += uchar4(ubo.u8);
|
||||
FragColorUint = uint4(tmp);
|
||||
}
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], constant Push& registers [[buffer(0)]], constant UBO& ubo [[buffer(0)]], device SSBO& ssbo [[buffer(1)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
packing_int8(ssbo);
|
||||
packing_uint8(ssbo);
|
||||
compute_int8(ssbo, in.vColor, registers, ubo, out.FragColorInt);
|
||||
compute_uint8(ssbo, in.vColor, registers, ubo, out.FragColorUint);
|
||||
return out;
|
||||
}
|
||||
|
@ -3,15 +3,11 @@
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
#elif defined(GL_NV_gpu_shader5)
|
||||
#extension GL_NV_gpu_shader5 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for FP16.
|
||||
#endif
|
||||
#if defined(GL_AMD_gpu_shader_int16)
|
||||
#extension GL_AMD_gpu_shader_int16 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for Int16.
|
||||
#endif
|
||||
|
@ -1,8 +1,6 @@
|
||||
#version 450
|
||||
#if defined(GL_AMD_gpu_shader_int16)
|
||||
#extension GL_AMD_gpu_shader_int16 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for Int16.
|
||||
#endif
|
||||
@ -10,8 +8,6 @@
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
#elif defined(GL_NV_gpu_shader5)
|
||||
#extension GL_NV_gpu_shader5 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for FP16.
|
||||
#endif
|
||||
|
@ -3,8 +3,6 @@
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
#elif defined(GL_NV_gpu_shader5)
|
||||
#extension GL_NV_gpu_shader5 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for FP16.
|
||||
#endif
|
||||
|
@ -3,15 +3,11 @@
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
#elif defined(GL_NV_gpu_shader5)
|
||||
#extension GL_NV_gpu_shader5 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for FP16.
|
||||
#endif
|
||||
#if defined(GL_AMD_gpu_shader_int16)
|
||||
#extension GL_AMD_gpu_shader_int16 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for Int16.
|
||||
#endif
|
||||
|
@ -0,0 +1,88 @@
|
||||
#version 450
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require
|
||||
#extension GL_EXT_shader_8bit_storage : require
|
||||
|
||||
layout(set = 0, binding = 1, std430) buffer SSBO
|
||||
{
|
||||
int8_t i8[16];
|
||||
uint8_t u8[16];
|
||||
} ssbo;
|
||||
|
||||
layout(set = 0, binding = 0, std140) uniform UBO
|
||||
{
|
||||
int8_t i8;
|
||||
uint8_t u8;
|
||||
} ubo;
|
||||
|
||||
layout(push_constant, std430) uniform Push
|
||||
{
|
||||
int8_t i8;
|
||||
uint8_t u8;
|
||||
} registers;
|
||||
|
||||
layout(location = 0) flat in ivec4 vColor;
|
||||
layout(location = 0) out ivec4 FragColorInt;
|
||||
layout(location = 1) out uvec4 FragColorUint;
|
||||
|
||||
void packing_int8()
|
||||
{
|
||||
int16_t i16 = 10s;
|
||||
int i32 = 20;
|
||||
i8vec2 i8_2 = unpack8(i16);
|
||||
i8vec4 i8_4 = unpack8(i32);
|
||||
i16 = pack16(i8_2);
|
||||
i32 = pack32(i8_4);
|
||||
ssbo.i8[0] = i8_4.x;
|
||||
ssbo.i8[1] = i8_4.y;
|
||||
ssbo.i8[2] = i8_4.z;
|
||||
ssbo.i8[3] = i8_4.w;
|
||||
}
|
||||
|
||||
void packing_uint8()
|
||||
{
|
||||
uint16_t u16 = 10us;
|
||||
uint u32 = 20u;
|
||||
u8vec2 u8_2 = unpack8(u16);
|
||||
u8vec4 u8_4 = unpack8(u32);
|
||||
u16 = pack16(u8_2);
|
||||
u32 = pack32(u8_4);
|
||||
ssbo.u8[0] = u8_4.x;
|
||||
ssbo.u8[1] = u8_4.y;
|
||||
ssbo.u8[2] = u8_4.z;
|
||||
ssbo.u8[3] = u8_4.w;
|
||||
}
|
||||
|
||||
void compute_int8()
|
||||
{
|
||||
i8vec4 tmp = i8vec4(vColor);
|
||||
tmp += i8vec4(registers.i8);
|
||||
tmp += i8vec4(int8_t(-40));
|
||||
tmp += i8vec4(-50);
|
||||
tmp += i8vec4(int8_t(10), int8_t(20), int8_t(30), int8_t(40));
|
||||
tmp += i8vec4(ssbo.i8[4]);
|
||||
tmp += i8vec4(ubo.i8);
|
||||
FragColorInt = ivec4(tmp);
|
||||
}
|
||||
|
||||
void compute_uint8()
|
||||
{
|
||||
u8vec4 tmp = u8vec4(i8vec4(vColor));
|
||||
tmp += u8vec4(registers.u8);
|
||||
tmp += u8vec4(uint8_t(216));
|
||||
tmp += u8vec4(206);
|
||||
tmp += u8vec4(uint8_t(10), uint8_t(20), uint8_t(30), uint8_t(40));
|
||||
tmp += u8vec4(ssbo.u8[4]);
|
||||
tmp += u8vec4(ubo.u8);
|
||||
FragColorUint = uvec4(tmp);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
packing_int8();
|
||||
packing_uint8();
|
||||
compute_int8();
|
||||
compute_uint8();
|
||||
}
|
||||
|
@ -1,18 +1,14 @@
|
||||
#version 450
|
||||
#if defined(GL_AMD_gpu_shader_int16)
|
||||
#extension GL_AMD_gpu_shader_int16 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for Int16.
|
||||
#endif
|
||||
#extension GL_EXT_shader_8bit_storage : require
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require
|
||||
#if defined(GL_AMD_gpu_shader_half_float)
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
#elif defined(GL_NV_gpu_shader5)
|
||||
#extension GL_NV_gpu_shader5 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for FP16.
|
||||
#endif
|
||||
|
@ -1,16 +1,12 @@
|
||||
#version 450
|
||||
#if defined(GL_AMD_gpu_shader_int16)
|
||||
#extension GL_AMD_gpu_shader_int16 : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#else
|
||||
#error No extension available for Int16.
|
||||
#endif
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require
|
||||
#extension GL_EXT_shader_8bit_storage : require
|
||||
#if defined(GL_AMD_gpu_shader_half_float)
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
#elif defined(GL_EXT_shader_16bit_storage)
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
#elif defined(GL_EXT_shader_explicit_arithmetic_types_float16)
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require
|
||||
#else
|
||||
#error No extension available for FP16.
|
||||
#endif
|
||||
|
88
shaders-msl/frag/shader-arithmetic-8bit.frag
Normal file
88
shaders-msl/frag/shader-arithmetic-8bit.frag
Normal file
@ -0,0 +1,88 @@
|
||||
#version 450
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require
|
||||
|
||||
layout(location = 0) flat in ivec4 vColor;
|
||||
layout(location = 0) out ivec4 FragColorInt;
|
||||
layout(location = 1) out uvec4 FragColorUint;
|
||||
|
||||
layout(push_constant, std140) uniform Push
|
||||
{
|
||||
int8_t i8;
|
||||
uint8_t u8;
|
||||
} registers;
|
||||
|
||||
layout(binding = 0, std140) uniform UBO
|
||||
{
|
||||
int8_t i8;
|
||||
uint8_t u8;
|
||||
} ubo;
|
||||
|
||||
layout(binding = 1, std430) buffer SSBO
|
||||
{
|
||||
int8_t i8[16];
|
||||
uint8_t u8[16];
|
||||
} ssbo;
|
||||
|
||||
void packing_int8()
|
||||
{
|
||||
int16_t i16 = 10s;
|
||||
int i32 = 20;
|
||||
|
||||
i8vec2 i8_2 = unpack8(i16);
|
||||
i8vec4 i8_4 = unpack8(i32);
|
||||
i16 = pack16(i8_2);
|
||||
i32 = pack32(i8_4);
|
||||
ssbo.i8[0] = i8_4.x;
|
||||
ssbo.i8[1] = i8_4.y;
|
||||
ssbo.i8[2] = i8_4.z;
|
||||
ssbo.i8[3] = i8_4.w;
|
||||
}
|
||||
|
||||
void packing_uint8()
|
||||
{
|
||||
uint16_t u16 = 10us;
|
||||
uint u32 = 20u;
|
||||
|
||||
u8vec2 u8_2 = unpack8(u16);
|
||||
u8vec4 u8_4 = unpack8(u32);
|
||||
u16 = pack16(u8_2);
|
||||
u32 = pack32(u8_4);
|
||||
|
||||
ssbo.u8[0] = u8_4.x;
|
||||
ssbo.u8[1] = u8_4.y;
|
||||
ssbo.u8[2] = u8_4.z;
|
||||
ssbo.u8[3] = u8_4.w;
|
||||
}
|
||||
|
||||
void compute_int8()
|
||||
{
|
||||
i8vec4 tmp = i8vec4(vColor);
|
||||
tmp += registers.i8;
|
||||
tmp += int8_t(-40);
|
||||
tmp += i8vec4(-50);
|
||||
tmp += i8vec4(10, 20, 30, 40);
|
||||
tmp += ssbo.i8[4];
|
||||
tmp += ubo.i8;
|
||||
FragColorInt = ivec4(tmp);
|
||||
}
|
||||
|
||||
void compute_uint8()
|
||||
{
|
||||
u8vec4 tmp = u8vec4(vColor);
|
||||
tmp += registers.u8;
|
||||
tmp += uint8_t(-40);
|
||||
tmp += u8vec4(-50);
|
||||
tmp += u8vec4(10, 20, 30, 40);
|
||||
tmp += ssbo.u8[4];
|
||||
tmp += ubo.u8;
|
||||
FragColorUint = uvec4(tmp);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
packing_int8();
|
||||
packing_uint8();
|
||||
compute_int8();
|
||||
compute_uint8();
|
||||
}
|
88
shaders/vulkan/frag/shader-arithmetic-8bit.nocompat.vk.frag
Normal file
88
shaders/vulkan/frag/shader-arithmetic-8bit.nocompat.vk.frag
Normal file
@ -0,0 +1,88 @@
|
||||
#version 450
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require
|
||||
|
||||
layout(location = 0) flat in ivec4 vColor;
|
||||
layout(location = 0) out ivec4 FragColorInt;
|
||||
layout(location = 1) out uvec4 FragColorUint;
|
||||
|
||||
layout(push_constant, std140) uniform Push
|
||||
{
|
||||
int8_t i8;
|
||||
uint8_t u8;
|
||||
} registers;
|
||||
|
||||
layout(binding = 0, std140) uniform UBO
|
||||
{
|
||||
int8_t i8;
|
||||
uint8_t u8;
|
||||
} ubo;
|
||||
|
||||
layout(binding = 1, std430) buffer SSBO
|
||||
{
|
||||
int8_t i8[16];
|
||||
uint8_t u8[16];
|
||||
} ssbo;
|
||||
|
||||
void packing_int8()
|
||||
{
|
||||
int16_t i16 = 10s;
|
||||
int i32 = 20;
|
||||
|
||||
i8vec2 i8_2 = unpack8(i16);
|
||||
i8vec4 i8_4 = unpack8(i32);
|
||||
i16 = pack16(i8_2);
|
||||
i32 = pack32(i8_4);
|
||||
ssbo.i8[0] = i8_4.x;
|
||||
ssbo.i8[1] = i8_4.y;
|
||||
ssbo.i8[2] = i8_4.z;
|
||||
ssbo.i8[3] = i8_4.w;
|
||||
}
|
||||
|
||||
void packing_uint8()
|
||||
{
|
||||
uint16_t u16 = 10us;
|
||||
uint u32 = 20u;
|
||||
|
||||
u8vec2 u8_2 = unpack8(u16);
|
||||
u8vec4 u8_4 = unpack8(u32);
|
||||
u16 = pack16(u8_2);
|
||||
u32 = pack32(u8_4);
|
||||
|
||||
ssbo.u8[0] = u8_4.x;
|
||||
ssbo.u8[1] = u8_4.y;
|
||||
ssbo.u8[2] = u8_4.z;
|
||||
ssbo.u8[3] = u8_4.w;
|
||||
}
|
||||
|
||||
void compute_int8()
|
||||
{
|
||||
i8vec4 tmp = i8vec4(vColor);
|
||||
tmp += registers.i8;
|
||||
tmp += int8_t(-40);
|
||||
tmp += i8vec4(-50);
|
||||
tmp += i8vec4(10, 20, 30, 40);
|
||||
tmp += ssbo.i8[4];
|
||||
tmp += ubo.i8;
|
||||
FragColorInt = ivec4(tmp);
|
||||
}
|
||||
|
||||
void compute_uint8()
|
||||
{
|
||||
u8vec4 tmp = u8vec4(vColor);
|
||||
tmp += registers.u8;
|
||||
tmp += uint8_t(-40);
|
||||
tmp += u8vec4(-50);
|
||||
tmp += u8vec4(10, 20, 30, 40);
|
||||
tmp += ssbo.u8[4];
|
||||
tmp += ubo.u8;
|
||||
FragColorUint = uvec4(tmp);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
packing_int8();
|
||||
packing_uint8();
|
||||
compute_int8();
|
||||
compute_uint8();
|
||||
}
|
@ -1047,6 +1047,16 @@ struct SPIRConstant : IVariant
|
||||
return uint16_t(m.c[col].r[row].u32 & 0xffffu);
|
||||
}
|
||||
|
||||
inline int8_t scalar_i8(uint32_t col = 0, uint32_t row = 0) const
|
||||
{
|
||||
return int8_t(m.c[col].r[row].u32 & 0xffu);
|
||||
}
|
||||
|
||||
inline uint8_t scalar_u8(uint32_t col = 0, uint32_t row = 0) const
|
||||
{
|
||||
return uint8_t(m.c[col].r[row].u32 & 0xffu);
|
||||
}
|
||||
|
||||
inline float scalar_f16(uint32_t col = 0, uint32_t row = 0) const
|
||||
{
|
||||
return f16_to_f32(scalar_u16(col, row));
|
||||
@ -1435,6 +1445,61 @@ static inline bool type_is_integral(const SPIRType &type)
|
||||
type.basetype == SPIRType::UShort || type.basetype == SPIRType::Int || type.basetype == SPIRType::UInt ||
|
||||
type.basetype == SPIRType::Int64 || type.basetype == SPIRType::UInt64;
|
||||
}
|
||||
|
||||
static inline SPIRType::BaseType to_signed_basetype(uint32_t width)
|
||||
{
|
||||
switch (width)
|
||||
{
|
||||
case 8:
|
||||
return SPIRType::SByte;
|
||||
case 16:
|
||||
return SPIRType::Short;
|
||||
case 32:
|
||||
return SPIRType::Int;
|
||||
case 64:
|
||||
return SPIRType::Int64;
|
||||
default:
|
||||
SPIRV_CROSS_THROW("Invalid bit width.");
|
||||
}
|
||||
}
|
||||
|
||||
static inline SPIRType::BaseType to_unsigned_basetype(uint32_t width)
|
||||
{
|
||||
switch (width)
|
||||
{
|
||||
case 8:
|
||||
return SPIRType::UByte;
|
||||
case 16:
|
||||
return SPIRType::UShort;
|
||||
case 32:
|
||||
return SPIRType::UInt;
|
||||
case 64:
|
||||
return SPIRType::UInt64;
|
||||
default:
|
||||
SPIRV_CROSS_THROW("Invalid bit width.");
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if an arithmetic operation does not change behavior depending on signedness.
|
||||
static inline bool opcode_is_sign_invariant(spv::Op opcode)
|
||||
{
|
||||
switch (opcode)
|
||||
{
|
||||
case spv::OpIEqual:
|
||||
case spv::OpINotEqual:
|
||||
case spv::OpISub:
|
||||
case spv::OpIAdd:
|
||||
case spv::OpIMul:
|
||||
case spv::OpShiftLeftLogical:
|
||||
case spv::OpBitwiseOr:
|
||||
case spv::OpBitwiseXor:
|
||||
case spv::OpBitwiseAnd:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} // namespace spirv_cross
|
||||
|
||||
#endif
|
||||
|
262
spirv_glsl.cpp
262
spirv_glsl.cpp
@ -149,27 +149,6 @@ string CompilerGLSL::sanitize_underscores(const string &str)
|
||||
return res;
|
||||
}
|
||||
|
||||
// Returns true if an arithmetic operation does not change behavior depending on signedness.
|
||||
static bool glsl_opcode_is_sign_invariant(Op opcode)
|
||||
{
|
||||
switch (opcode)
|
||||
{
|
||||
case OpIEqual:
|
||||
case OpINotEqual:
|
||||
case OpISub:
|
||||
case OpIAdd:
|
||||
case OpIMul:
|
||||
case OpShiftLeftLogical:
|
||||
case OpBitwiseOr:
|
||||
case OpBitwiseXor:
|
||||
case OpBitwiseAnd:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *to_pls_layout(PlsFormat format)
|
||||
{
|
||||
switch (format)
|
||||
@ -342,23 +321,31 @@ void CompilerGLSL::find_static_extensions()
|
||||
if (!options.es && options.version < 400)
|
||||
require_extension_internal("GL_ARB_gpu_shader_fp64");
|
||||
}
|
||||
|
||||
if (type.basetype == SPIRType::Int64 || type.basetype == SPIRType::UInt64)
|
||||
else if (type.basetype == SPIRType::Int64 || type.basetype == SPIRType::UInt64)
|
||||
{
|
||||
if (options.es)
|
||||
SPIRV_CROSS_THROW("64-bit integers not supported in ES profile.");
|
||||
if (!options.es)
|
||||
require_extension_internal("GL_ARB_gpu_shader_int64");
|
||||
}
|
||||
|
||||
if (type.basetype == SPIRType::Half)
|
||||
require_extension_internal("GL_AMD_gpu_shader_half_float");
|
||||
|
||||
if (type.basetype == SPIRType::SByte || type.basetype == SPIRType::UByte)
|
||||
require_extension_internal("GL_EXT_shader_8bit_storage");
|
||||
|
||||
if (type.basetype == SPIRType::Short || type.basetype == SPIRType::UShort)
|
||||
require_extension_internal("GL_AMD_gpu_shader_int16");
|
||||
else if (type.basetype == SPIRType::Half)
|
||||
{
|
||||
require_extension_internal("GL_EXT_shader_explicit_arithmetic_types_float16");
|
||||
if (options.vulkan_semantics)
|
||||
require_extension_internal("GL_EXT_shader_16bit_storage");
|
||||
}
|
||||
else if (type.basetype == SPIRType::SByte || type.basetype == SPIRType::UByte)
|
||||
{
|
||||
require_extension_internal("GL_EXT_shader_explicit_arithmetic_types_int8");
|
||||
if (options.vulkan_semantics)
|
||||
require_extension_internal("GL_EXT_shader_8bit_storage");
|
||||
}
|
||||
else if (type.basetype == SPIRType::Short || type.basetype == SPIRType::UShort)
|
||||
{
|
||||
require_extension_internal("GL_EXT_shader_explicit_arithmetic_types_int16");
|
||||
if (options.vulkan_semantics)
|
||||
require_extension_internal("GL_EXT_shader_16bit_storage");
|
||||
}
|
||||
});
|
||||
|
||||
auto &execution = get_entry_point();
|
||||
@ -508,7 +495,7 @@ void CompilerGLSL::emit_header()
|
||||
|
||||
for (auto &ext : forced_extensions)
|
||||
{
|
||||
if (ext == "GL_AMD_gpu_shader_half_float")
|
||||
if (ext == "GL_EXT_shader_explicit_arithmetic_types_float16")
|
||||
{
|
||||
// Special case, this extension has a potential fallback to another vendor extension in normal GLSL.
|
||||
// GL_AMD_gpu_shader_half_float is a superset, so try that first.
|
||||
@ -519,22 +506,27 @@ void CompilerGLSL::emit_header()
|
||||
statement("#elif defined(GL_NV_gpu_shader5)");
|
||||
statement("#extension GL_NV_gpu_shader5 : require");
|
||||
}
|
||||
statement("#elif defined(GL_EXT_shader_16bit_storage)");
|
||||
statement("#extension GL_EXT_shader_16bit_storage : require");
|
||||
else
|
||||
{
|
||||
statement("#elif defined(GL_EXT_shader_explicit_arithmetic_types_float16)");
|
||||
statement("#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require");
|
||||
}
|
||||
statement("#else");
|
||||
statement("#error No extension available for FP16.");
|
||||
statement("#endif");
|
||||
}
|
||||
else if (ext == "GL_AMD_gpu_shader_int16")
|
||||
else if (ext == "GL_EXT_shader_explicit_arithmetic_types_int16")
|
||||
{
|
||||
// GL_AMD_gpu_shader_int16 is a superset, so try that first.
|
||||
statement("#if defined(GL_AMD_gpu_shader_int16)");
|
||||
statement("#extension GL_AMD_gpu_shader_int16 : require");
|
||||
statement("#elif defined(GL_EXT_shader_16bit_storage)");
|
||||
statement("#extension GL_EXT_shader_16bit_storage : require");
|
||||
statement("#else");
|
||||
statement("#error No extension available for Int16.");
|
||||
statement("#endif");
|
||||
if (options.vulkan_semantics)
|
||||
statement("#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require");
|
||||
else
|
||||
{
|
||||
statement("#if defined(GL_AMD_gpu_shader_int16)");
|
||||
statement("#extension GL_AMD_gpu_shader_int16 : require");
|
||||
statement("#else");
|
||||
statement("#error No extension available for Int16.");
|
||||
statement("#endif");
|
||||
}
|
||||
}
|
||||
else
|
||||
statement("#extension ", ext, " : require");
|
||||
@ -2799,14 +2791,38 @@ string CompilerGLSL::constant_op_expression(const SPIRConstantOp &cop)
|
||||
SPIRV_CROSS_THROW("Unimplemented spec constant op.");
|
||||
}
|
||||
|
||||
uint32_t bit_width = 0;
|
||||
if (unary || binary)
|
||||
bit_width = expression_type(cop.arguments[0]).width;
|
||||
|
||||
SPIRType::BaseType input_type;
|
||||
bool skip_cast_if_equal_type = glsl_opcode_is_sign_invariant(cop.opcode);
|
||||
bool skip_cast_if_equal_type = opcode_is_sign_invariant(cop.opcode);
|
||||
|
||||
switch (cop.opcode)
|
||||
{
|
||||
case OpIEqual:
|
||||
case OpINotEqual:
|
||||
input_type = SPIRType::Int;
|
||||
input_type = to_signed_basetype(bit_width);
|
||||
break;
|
||||
|
||||
case OpSLessThan:
|
||||
case OpSLessThanEqual:
|
||||
case OpSGreaterThan:
|
||||
case OpSGreaterThanEqual:
|
||||
case OpSMod:
|
||||
case OpSDiv:
|
||||
case OpShiftRightArithmetic:
|
||||
input_type = to_signed_basetype(bit_width);
|
||||
break;
|
||||
|
||||
case OpULessThan:
|
||||
case OpULessThanEqual:
|
||||
case OpUGreaterThan:
|
||||
case OpUGreaterThanEqual:
|
||||
case OpUMod:
|
||||
case OpUDiv:
|
||||
case OpShiftRightLogical:
|
||||
input_type = to_unsigned_basetype(bit_width);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -3121,6 +3137,9 @@ string CompilerGLSL::constant_expression_vector(const SPIRConstant &c, uint32_t
|
||||
auto type = get<SPIRType>(c.constant_type);
|
||||
type.columns = 1;
|
||||
|
||||
auto scalar_type = type;
|
||||
scalar_type.vecsize = 1;
|
||||
|
||||
string res;
|
||||
bool splat = backend.use_constructor_splatting && c.vector_size() > 1;
|
||||
bool swizzle_splat = backend.can_swizzle_scalar && c.vector_size() > 1;
|
||||
@ -3429,6 +3448,56 @@ string CompilerGLSL::constant_expression_vector(const SPIRConstant &c, uint32_t
|
||||
}
|
||||
break;
|
||||
|
||||
case SPIRType::UByte:
|
||||
if (splat)
|
||||
{
|
||||
res += convert_to_string(c.scalar_u8(vector, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t i = 0; i < c.vector_size(); i++)
|
||||
{
|
||||
if (c.vector_size() > 1 && c.specialization_constant_id(vector, i) != 0)
|
||||
res += to_name(c.specialization_constant_id(vector, i));
|
||||
else
|
||||
{
|
||||
res += type_to_glsl(scalar_type);
|
||||
res += "(";
|
||||
res += convert_to_string(c.scalar_u8(vector, i));
|
||||
res += ")";
|
||||
}
|
||||
|
||||
if (i + 1 < c.vector_size())
|
||||
res += ", ";
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SPIRType::SByte:
|
||||
if (splat)
|
||||
{
|
||||
res += convert_to_string(c.scalar_i8(vector, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t i = 0; i < c.vector_size(); i++)
|
||||
{
|
||||
if (c.vector_size() > 1 && c.specialization_constant_id(vector, i) != 0)
|
||||
res += to_name(c.specialization_constant_id(vector, i));
|
||||
else
|
||||
{
|
||||
res += type_to_glsl(scalar_type);
|
||||
res += "(";
|
||||
res += convert_to_string(c.scalar_i8(vector, i));
|
||||
res += ")";
|
||||
}
|
||||
|
||||
if (i + 1 < c.vector_size())
|
||||
res += ", ";
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SPIRType::Boolean:
|
||||
if (splat)
|
||||
res += c.scalar(vector, 0) ? "true" : "false";
|
||||
@ -5185,20 +5254,31 @@ case OpGroupNonUniform##op: \
|
||||
|
||||
string CompilerGLSL::bitcast_glsl_op(const SPIRType &out_type, const SPIRType &in_type)
|
||||
{
|
||||
if (out_type.basetype == SPIRType::UShort && in_type.basetype == SPIRType::Short)
|
||||
assert(out_type.basetype != SPIRType::Boolean);
|
||||
assert(in_type.basetype != SPIRType::Boolean);
|
||||
|
||||
if (out_type.basetype == in_type.basetype)
|
||||
return "";
|
||||
|
||||
bool integral_cast = type_is_integral(out_type) && type_is_integral(in_type);
|
||||
bool same_size_cast = out_type.width == in_type.width;
|
||||
|
||||
// Trivial bitcast case, casts between integers.
|
||||
if (integral_cast && same_size_cast)
|
||||
return type_to_glsl(out_type);
|
||||
else if (out_type.basetype == SPIRType::UInt && in_type.basetype == SPIRType::Int)
|
||||
return type_to_glsl(out_type);
|
||||
else if (out_type.basetype == SPIRType::UInt64 && in_type.basetype == SPIRType::Int64)
|
||||
return type_to_glsl(out_type);
|
||||
else if (out_type.basetype == SPIRType::UInt && in_type.basetype == SPIRType::Float)
|
||||
|
||||
// Catch-all 8-bit arithmetic casts (GL_EXT_shader_explicit_arithmetic_types).
|
||||
if (out_type.width == 8 && in_type.width >= 16 && integral_cast && in_type.vecsize == 1)
|
||||
return "unpack8";
|
||||
else if (in_type.width == 8 && out_type.width == 16 && integral_cast && out_type.vecsize == 1)
|
||||
return "pack16";
|
||||
else if (in_type.width == 8 && out_type.width == 32 && integral_cast && out_type.vecsize == 1)
|
||||
return "pack32";
|
||||
|
||||
// Floating <-> Integer special casts. Just have to enumerate all cases. :(
|
||||
// 16-bit, 32-bit and 64-bit floats.
|
||||
if (out_type.basetype == SPIRType::UInt && in_type.basetype == SPIRType::Float)
|
||||
return "floatBitsToUint";
|
||||
else if (out_type.basetype == SPIRType::Short && in_type.basetype == SPIRType::UShort)
|
||||
return type_to_glsl(out_type);
|
||||
else if (out_type.basetype == SPIRType::Int && in_type.basetype == SPIRType::UInt)
|
||||
return type_to_glsl(out_type);
|
||||
else if (out_type.basetype == SPIRType::Int64 && in_type.basetype == SPIRType::UInt64)
|
||||
return type_to_glsl(out_type);
|
||||
else if (out_type.basetype == SPIRType::Int && in_type.basetype == SPIRType::Float)
|
||||
return "floatBitsToInt";
|
||||
else if (out_type.basetype == SPIRType::Float && in_type.basetype == SPIRType::UInt)
|
||||
@ -5221,7 +5301,9 @@ string CompilerGLSL::bitcast_glsl_op(const SPIRType &out_type, const SPIRType &i
|
||||
return "int16BitsToFloat16";
|
||||
else if (out_type.basetype == SPIRType::Half && in_type.basetype == SPIRType::UShort)
|
||||
return "uint16BitsToFloat16";
|
||||
else if (out_type.basetype == SPIRType::UInt64 && in_type.basetype == SPIRType::UInt && in_type.vecsize == 2)
|
||||
|
||||
// And finally, some even more special purpose casts.
|
||||
if (out_type.basetype == SPIRType::UInt64 && in_type.basetype == SPIRType::UInt && in_type.vecsize == 2)
|
||||
return "packUint2x32";
|
||||
else if (out_type.basetype == SPIRType::Half && in_type.basetype == SPIRType::UInt && in_type.vecsize == 1)
|
||||
return "unpackFloat2x16";
|
||||
@ -5243,8 +5325,8 @@ string CompilerGLSL::bitcast_glsl_op(const SPIRType &out_type, const SPIRType &i
|
||||
return "packUint4x16";
|
||||
else if (out_type.basetype == SPIRType::UShort && in_type.basetype == SPIRType::UInt64 && in_type.vecsize == 1)
|
||||
return "unpackUint4x16";
|
||||
else
|
||||
return "";
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
string CompilerGLSL::bitcast_glsl(const SPIRType &result_type, uint32_t argument)
|
||||
@ -6662,6 +6744,35 @@ void CompilerGLSL::emit_store_statement(uint32_t lhs_expression, uint32_t rhs_ex
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t CompilerGLSL::get_integer_width_for_instruction(const Instruction &instr) const
|
||||
{
|
||||
if (instr.length < 3)
|
||||
return 32;
|
||||
|
||||
auto *ops = stream(instr);
|
||||
|
||||
switch (instr.op)
|
||||
{
|
||||
case OpIEqual:
|
||||
case OpINotEqual:
|
||||
case OpSLessThan:
|
||||
case OpSLessThanEqual:
|
||||
case OpSGreaterThan:
|
||||
case OpSGreaterThanEqual:
|
||||
return expression_type(ops[2]).width;
|
||||
|
||||
default:
|
||||
{
|
||||
// We can look at result type which is more robust.
|
||||
auto *type = maybe_get<SPIRType>(ops[0]);
|
||||
if (type && type_is_integral(*type))
|
||||
return type->width;
|
||||
else
|
||||
return 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
||||
{
|
||||
auto ops = stream(instruction);
|
||||
@ -6670,16 +6781,21 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
||||
|
||||
#define GLSL_BOP(op) emit_binary_op(ops[0], ops[1], ops[2], ops[3], #op)
|
||||
#define GLSL_BOP_CAST(op, type) \
|
||||
emit_binary_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, glsl_opcode_is_sign_invariant(opcode))
|
||||
emit_binary_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, opcode_is_sign_invariant(opcode))
|
||||
#define GLSL_UOP(op) emit_unary_op(ops[0], ops[1], ops[2], #op)
|
||||
#define GLSL_QFOP(op) emit_quaternary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], ops[5], #op)
|
||||
#define GLSL_TFOP(op) emit_trinary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], #op)
|
||||
#define GLSL_BFOP(op) emit_binary_func_op(ops[0], ops[1], ops[2], ops[3], #op)
|
||||
#define GLSL_BFOP_CAST(op, type) \
|
||||
emit_binary_func_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, glsl_opcode_is_sign_invariant(opcode))
|
||||
emit_binary_func_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, opcode_is_sign_invariant(opcode))
|
||||
#define GLSL_BFOP(op) emit_binary_func_op(ops[0], ops[1], ops[2], ops[3], #op)
|
||||
#define GLSL_UFOP(op) emit_unary_func_op(ops[0], ops[1], ops[2], #op)
|
||||
|
||||
// If we need to do implicit bitcasts, make sure we do it with the correct type.
|
||||
uint32_t integer_width = get_integer_width_for_instruction(instruction);
|
||||
auto int_type = to_signed_basetype(integer_width);
|
||||
auto uint_type = to_unsigned_basetype(integer_width);
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
// Dealing with memory
|
||||
@ -7357,11 +7473,11 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
||||
}
|
||||
|
||||
case OpSDiv:
|
||||
GLSL_BOP_CAST(/, SPIRType::Int);
|
||||
GLSL_BOP_CAST(/, int_type);
|
||||
break;
|
||||
|
||||
case OpUDiv:
|
||||
GLSL_BOP_CAST(/, SPIRType::UInt);
|
||||
GLSL_BOP_CAST(/, uint_type);
|
||||
break;
|
||||
|
||||
case OpIAddCarry:
|
||||
@ -7419,11 +7535,11 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
||||
break;
|
||||
|
||||
case OpShiftRightLogical:
|
||||
GLSL_BOP_CAST(>>, SPIRType::UInt);
|
||||
GLSL_BOP_CAST(>>, uint_type);
|
||||
break;
|
||||
|
||||
case OpShiftRightArithmetic:
|
||||
GLSL_BOP_CAST(>>, SPIRType::Int);
|
||||
GLSL_BOP_CAST(>>, int_type);
|
||||
break;
|
||||
|
||||
case OpShiftLeftLogical:
|
||||
@ -7459,11 +7575,11 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
||||
break;
|
||||
|
||||
case OpUMod:
|
||||
GLSL_BOP_CAST(%, SPIRType::UInt);
|
||||
GLSL_BOP_CAST(%, uint_type);
|
||||
break;
|
||||
|
||||
case OpSMod:
|
||||
GLSL_BOP_CAST(%, SPIRType::Int);
|
||||
GLSL_BOP_CAST(%, int_type);
|
||||
break;
|
||||
|
||||
case OpFMod:
|
||||
@ -7546,9 +7662,9 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
||||
case OpIEqual:
|
||||
{
|
||||
if (expression_type(ops[2]).vecsize > 1)
|
||||
GLSL_BFOP_CAST(equal, SPIRType::Int);
|
||||
GLSL_BFOP_CAST(equal, int_type);
|
||||
else
|
||||
GLSL_BOP_CAST(==, SPIRType::Int);
|
||||
GLSL_BOP_CAST(==, int_type);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -7565,9 +7681,9 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
||||
case OpINotEqual:
|
||||
{
|
||||
if (expression_type(ops[2]).vecsize > 1)
|
||||
GLSL_BFOP_CAST(notEqual, SPIRType::Int);
|
||||
GLSL_BFOP_CAST(notEqual, int_type);
|
||||
else
|
||||
GLSL_BOP_CAST(!=, SPIRType::Int);
|
||||
GLSL_BOP_CAST(!=, int_type);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -636,6 +636,8 @@ protected:
|
||||
bool expression_is_constant_null(uint32_t id) const;
|
||||
virtual void emit_store_statement(uint32_t lhs_expression, uint32_t rhs_expression);
|
||||
|
||||
uint32_t get_integer_width_for_instruction(const Instruction &instr) const;
|
||||
|
||||
private:
|
||||
void init()
|
||||
{
|
||||
|
@ -203,27 +203,6 @@ static string image_format_to_type(ImageFormat fmt, SPIRType::BaseType basetype)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if an arithmetic operation does not change behavior depending on signedness.
|
||||
static bool hlsl_opcode_is_sign_invariant(Op opcode)
|
||||
{
|
||||
switch (opcode)
|
||||
{
|
||||
case OpIEqual:
|
||||
case OpINotEqual:
|
||||
case OpISub:
|
||||
case OpIAdd:
|
||||
case OpIMul:
|
||||
case OpShiftLeftLogical:
|
||||
case OpBitwiseOr:
|
||||
case OpBitwiseXor:
|
||||
case OpBitwiseAnd:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
string CompilerHLSL::image_type_hlsl_modern(const SPIRType &type, uint32_t)
|
||||
{
|
||||
auto &imagetype = get<SPIRType>(type.image.type);
|
||||
@ -3896,16 +3875,20 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
|
||||
|
||||
#define HLSL_BOP(op) emit_binary_op(ops[0], ops[1], ops[2], ops[3], #op)
|
||||
#define HLSL_BOP_CAST(op, type) \
|
||||
emit_binary_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, hlsl_opcode_is_sign_invariant(opcode))
|
||||
emit_binary_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, opcode_is_sign_invariant(opcode))
|
||||
#define HLSL_UOP(op) emit_unary_op(ops[0], ops[1], ops[2], #op)
|
||||
#define HLSL_QFOP(op) emit_quaternary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], ops[5], #op)
|
||||
#define HLSL_TFOP(op) emit_trinary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], #op)
|
||||
#define HLSL_BFOP(op) emit_binary_func_op(ops[0], ops[1], ops[2], ops[3], #op)
|
||||
#define HLSL_BFOP_CAST(op, type) \
|
||||
emit_binary_func_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, hlsl_opcode_is_sign_invariant(opcode))
|
||||
emit_binary_func_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, opcode_is_sign_invariant(opcode))
|
||||
#define HLSL_BFOP(op) emit_binary_func_op(ops[0], ops[1], ops[2], ops[3], #op)
|
||||
#define HLSL_UFOP(op) emit_unary_func_op(ops[0], ops[1], ops[2], #op)
|
||||
|
||||
// If we need to do implicit bitcasts, make sure we do it with the correct type.
|
||||
uint32_t integer_width = get_integer_width_for_instruction(instruction);
|
||||
auto int_type = to_signed_basetype(integer_width);
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case OpAccessChain:
|
||||
@ -4041,7 +4024,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
|
||||
if (expression_type(ops[2]).vecsize > 1)
|
||||
emit_unrolled_binary_op(result_type, id, ops[2], ops[3], "==");
|
||||
else
|
||||
HLSL_BOP_CAST(==, SPIRType::Int);
|
||||
HLSL_BOP_CAST(==, int_type);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4066,7 +4049,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
|
||||
if (expression_type(ops[2]).vecsize > 1)
|
||||
emit_unrolled_binary_op(result_type, id, ops[2], ops[3], "!=");
|
||||
else
|
||||
HLSL_BOP_CAST(!=, SPIRType::Int);
|
||||
HLSL_BOP_CAST(!=, int_type);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2441,7 +2441,6 @@ void CompilerMSL::emit_binary_unord_op(uint32_t result_type, uint32_t result_id,
|
||||
// Override for MSL-specific syntax instructions
|
||||
void CompilerMSL::emit_instruction(const Instruction &instruction)
|
||||
{
|
||||
|
||||
#define MSL_BOP(op) emit_binary_op(ops[0], ops[1], ops[2], ops[3], #op)
|
||||
#define MSL_BOP_CAST(op, type) \
|
||||
emit_binary_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, opcode_is_sign_invariant(opcode))
|
||||
@ -2457,42 +2456,77 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
|
||||
auto ops = stream(instruction);
|
||||
auto opcode = static_cast<Op>(instruction.op);
|
||||
|
||||
// If we need to do implicit bitcasts, make sure we do it with the correct type.
|
||||
uint32_t integer_width = get_integer_width_for_instruction(instruction);
|
||||
auto int_type = to_signed_basetype(integer_width);
|
||||
auto uint_type = to_unsigned_basetype(integer_width);
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
|
||||
// Comparisons
|
||||
case OpIEqual:
|
||||
MSL_BOP_CAST(==, int_type);
|
||||
break;
|
||||
|
||||
case OpLogicalEqual:
|
||||
case OpFOrdEqual:
|
||||
MSL_BOP(==);
|
||||
break;
|
||||
|
||||
case OpINotEqual:
|
||||
MSL_BOP_CAST(!=, int_type);
|
||||
break;
|
||||
|
||||
case OpLogicalNotEqual:
|
||||
case OpFOrdNotEqual:
|
||||
MSL_BOP(!=);
|
||||
break;
|
||||
|
||||
case OpUGreaterThan:
|
||||
MSL_BOP_CAST(>, uint_type);
|
||||
break;
|
||||
|
||||
case OpSGreaterThan:
|
||||
MSL_BOP_CAST(>, int_type);
|
||||
break;
|
||||
|
||||
case OpFOrdGreaterThan:
|
||||
MSL_BOP(>);
|
||||
break;
|
||||
|
||||
case OpUGreaterThanEqual:
|
||||
MSL_BOP_CAST(>=, uint_type);
|
||||
break;
|
||||
|
||||
case OpSGreaterThanEqual:
|
||||
MSL_BOP_CAST(>=, int_type);
|
||||
break;
|
||||
|
||||
case OpFOrdGreaterThanEqual:
|
||||
MSL_BOP(>=);
|
||||
break;
|
||||
|
||||
case OpULessThan:
|
||||
MSL_BOP_CAST(<, uint_type);
|
||||
break;
|
||||
|
||||
case OpSLessThan:
|
||||
MSL_BOP_CAST(<, int_type);
|
||||
break;
|
||||
|
||||
case OpFOrdLessThan:
|
||||
MSL_BOP(<);
|
||||
break;
|
||||
|
||||
case OpULessThanEqual:
|
||||
MSL_BOP_CAST(<=, uint_type);
|
||||
break;
|
||||
|
||||
case OpSLessThanEqual:
|
||||
MSL_BOP_CAST(<=, int_type);
|
||||
break;
|
||||
|
||||
case OpFOrdLessThanEqual:
|
||||
MSL_BOP(<=);
|
||||
break;
|
||||
@ -5433,37 +5467,25 @@ string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id)
|
||||
|
||||
string CompilerMSL::bitcast_glsl_op(const SPIRType &out_type, const SPIRType &in_type)
|
||||
{
|
||||
if ((out_type.basetype == SPIRType::UShort && in_type.basetype == SPIRType::Short) ||
|
||||
(out_type.basetype == SPIRType::Short && in_type.basetype == SPIRType::UShort) ||
|
||||
(out_type.basetype == SPIRType::UInt && in_type.basetype == SPIRType::Int) ||
|
||||
(out_type.basetype == SPIRType::Int && in_type.basetype == SPIRType::UInt) ||
|
||||
(out_type.basetype == SPIRType::UInt64 && in_type.basetype == SPIRType::Int64) ||
|
||||
(out_type.basetype == SPIRType::Int64 && in_type.basetype == SPIRType::UInt64))
|
||||
assert(out_type.basetype != SPIRType::Boolean);
|
||||
assert(in_type.basetype != SPIRType::Boolean);
|
||||
|
||||
if (out_type.basetype == in_type.basetype)
|
||||
return "";
|
||||
|
||||
bool integral_cast = type_is_integral(out_type) && type_is_integral(in_type);
|
||||
bool same_size_cast = out_type.width == in_type.width;
|
||||
|
||||
if (integral_cast && same_size_cast)
|
||||
{
|
||||
// Trivial bitcast case, casts between integers.
|
||||
return type_to_glsl(out_type);
|
||||
|
||||
if ((out_type.basetype == SPIRType::UInt && in_type.basetype == SPIRType::Float) ||
|
||||
(out_type.basetype == SPIRType::Int && in_type.basetype == SPIRType::Float) ||
|
||||
(out_type.basetype == SPIRType::Float && in_type.basetype == SPIRType::UInt) ||
|
||||
(out_type.basetype == SPIRType::Float && in_type.basetype == SPIRType::Int) ||
|
||||
(out_type.basetype == SPIRType::Int64 && in_type.basetype == SPIRType::Double) ||
|
||||
(out_type.basetype == SPIRType::UInt64 && in_type.basetype == SPIRType::Double) ||
|
||||
(out_type.basetype == SPIRType::Double && in_type.basetype == SPIRType::Int64) ||
|
||||
(out_type.basetype == SPIRType::Double && in_type.basetype == SPIRType::UInt64) ||
|
||||
(out_type.basetype == SPIRType::Half && in_type.basetype == SPIRType::UInt) ||
|
||||
(out_type.basetype == SPIRType::UInt && in_type.basetype == SPIRType::Half) ||
|
||||
(out_type.basetype == SPIRType::Half && in_type.basetype == SPIRType::Int) ||
|
||||
(out_type.basetype == SPIRType::Int && in_type.basetype == SPIRType::Half) ||
|
||||
(out_type.basetype == SPIRType::Half && in_type.basetype == SPIRType::UShort) ||
|
||||
(out_type.basetype == SPIRType::UShort && in_type.basetype == SPIRType::Half) ||
|
||||
(out_type.basetype == SPIRType::Half && in_type.basetype == SPIRType::Short) ||
|
||||
(out_type.basetype == SPIRType::Short && in_type.basetype == SPIRType::Half) ||
|
||||
(out_type.basetype == SPIRType::UInt && in_type.basetype == SPIRType::UShort && in_type.vecsize == 2) ||
|
||||
(out_type.basetype == SPIRType::UShort && in_type.basetype == SPIRType::UInt && in_type.vecsize == 1) ||
|
||||
(out_type.basetype == SPIRType::Int && in_type.basetype == SPIRType::Short && in_type.vecsize == 2) ||
|
||||
(out_type.basetype == SPIRType::Short && in_type.basetype == SPIRType::Int && in_type.vecsize == 1))
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fall back to the catch-all bitcast in MSL.
|
||||
return "as_type<" + type_to_glsl(out_type) + ">";
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// Returns an MSL string identifying the name of a SPIR-V builtin.
|
||||
|
@ -461,23 +461,7 @@ void Parser::parse(const Instruction &instruction)
|
||||
uint32_t width = ops[1];
|
||||
bool signedness = ops[2] != 0;
|
||||
auto &type = set<SPIRType>(id);
|
||||
switch (width)
|
||||
{
|
||||
case 64:
|
||||
type.basetype = signedness ? SPIRType::Int64 : SPIRType::UInt64;
|
||||
break;
|
||||
case 32:
|
||||
type.basetype = signedness ? SPIRType::Int : SPIRType::UInt;
|
||||
break;
|
||||
case 16:
|
||||
type.basetype = signedness ? SPIRType::Short : SPIRType::UShort;
|
||||
break;
|
||||
case 8:
|
||||
type.basetype = signedness ? SPIRType::SByte : SPIRType::UByte;
|
||||
break;
|
||||
default:
|
||||
SPIRV_CROSS_THROW("Unrecognized bit-width of integral type.");
|
||||
}
|
||||
type.basetype = signedness ? to_signed_basetype(width) : to_unsigned_basetype(width);
|
||||
type.width = width;
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user