Commit 24c49ddd by Alexis Hetu Committed by Alexis Hétu

R11G11B10F support

- Moved the R11G11B10F conversion code from the Blitter to ShaderCore - Used the conversion code in PixelRoutine where appropriate to make the R11G11B10F work as a renderable format - Added the VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT and VK_FORMAT_FEATURE_BLIT_DST_BIT to the VK_FORMAT_B10G11R11_UFLOAT_PACK32 format This allows ANGLE to expose the GL_EXT_color_buffer_float (and GL_EXT_color_buffer_half_float, which depends on GL_EXT_color_buffer_float in ANGLE, due a driver issue). Bug: b/146223877 Tests: dEQP-VK.*b10g11r11* Change-Id: I04ad29f7b7d497705186ae290a05868abfc13c42 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/39550 Presubmit-Ready: Alexis Hétu <sugoi@google.com> Reviewed-by: 's avatarAntonio Maiorano <amaiorano@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Tested-by: 's avatarAlexis Hétu <sugoi@google.com>
parent fbbfeb70
...@@ -398,19 +398,7 @@ Float4 Blitter::readFloat4(Pointer<Byte> element, const State &state) ...@@ -398,19 +398,7 @@ Float4 Blitter::readFloat4(Pointer<Byte> element, const State &state)
c.x = Float(*Pointer<Half>(element)); c.x = Float(*Pointer<Half>(element));
break; break;
case VK_FORMAT_B10G11R11_UFLOAT_PACK32: case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
// 10 (or 11) bit float formats are unsigned formats with a 5 bit exponent and a 5 (or 6) bit mantissa. c = r11g11b10Unpack(*Pointer<UInt>(element));
// Since the Half float format also has a 5 bit exponent, we can convert these formats to half by
// copy/pasting the bits so the the exponent bits and top mantissa bits are aligned to the half format.
// In this case, we have:
// B B B B B B B B B B G G G G G G G G G G G R R R R R R R R R R R
// 1st Short: |xxxxxxxxxx---------------------|
// 2nd Short: |xxxx---------------------xxxxxx|
// 3rd Short: |--------------------xxxxxxxxxxxx|
// These memory reads overlap, but each of them contains an entire channel, so we can read this without
// any int -> short conversion.
c.x = Float(As<Half>((*Pointer<UShort>(element + 0) & UShort(0x07FF)) << UShort(4)));
c.y = Float(As<Half>((*Pointer<UShort>(element + 1) & UShort(0x3FF8)) << UShort(1)));
c.z = Float(As<Half>((*Pointer<UShort>(element + 2) & UShort(0xFFC0)) >> UShort(1)));
break; break;
case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
// This type contains a common 5 bit exponent (E) and a 9 bit the mantissa for R, G and B. // This type contains a common 5 bit exponent (E) and a 9 bit the mantissa for R, G and B.
...@@ -621,16 +609,7 @@ void Blitter::write(Float4 &c, Pointer<Byte> element, const State &state) ...@@ -621,16 +609,7 @@ void Blitter::write(Float4 &c, Pointer<Byte> element, const State &state)
break; break;
case VK_FORMAT_B10G11R11_UFLOAT_PACK32: case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
{ {
// 10 (or 11) bit float formats are unsigned formats with a 5 bit exponent and a 5 (or 6) bit mantissa. UInt rgb = r11g11b10Pack(c);
// Since the 16-bit half-precision float format also has a 5 bit exponent, we can extract these minifloats from them.
// FIXME(b/138944025): Handle negative values, Inf, and NaN.
// FIXME(b/138944025): Perform rounding before truncating the mantissa.
UInt r = (UInt(As<UShort>(Half(c.x))) & 0x00007FF0) >> 4;
UInt g = (UInt(As<UShort>(Half(c.y))) & 0x00007FF0) << 7;
UInt b = (UInt(As<UShort>(Half(c.z))) & 0x00007FE0) << 17;
UInt rgb = r | g | b;
UInt old = *Pointer<UInt>(element); UInt old = *Pointer<UInt>(element);
......
...@@ -244,6 +244,7 @@ void PixelProgram::rasterOperation(Pointer<Byte> cBuffer[4], Int &x, Int sMask[4 ...@@ -244,6 +244,7 @@ void PixelProgram::rasterOperation(Pointer<Byte> cBuffer[4], Int &x, Int sMask[4
case VK_FORMAT_R16_SFLOAT: case VK_FORMAT_R16_SFLOAT:
case VK_FORMAT_R16G16_SFLOAT: case VK_FORMAT_R16G16_SFLOAT:
case VK_FORMAT_R16G16B16A16_SFLOAT: case VK_FORMAT_R16G16B16A16_SFLOAT:
case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
case VK_FORMAT_R32_SFLOAT: case VK_FORMAT_R32_SFLOAT:
case VK_FORMAT_R32G32_SFLOAT: case VK_FORMAT_R32G32_SFLOAT:
case VK_FORMAT_R32G32B32A32_SFLOAT: case VK_FORMAT_R32G32B32A32_SFLOAT:
...@@ -329,6 +330,7 @@ void PixelProgram::clampColor(Vector4f oC[RENDERTARGETS]) ...@@ -329,6 +330,7 @@ void PixelProgram::clampColor(Vector4f oC[RENDERTARGETS])
case VK_FORMAT_R16_SFLOAT: case VK_FORMAT_R16_SFLOAT:
case VK_FORMAT_R16G16_SFLOAT: case VK_FORMAT_R16G16_SFLOAT:
case VK_FORMAT_R16G16B16A16_SFLOAT: case VK_FORMAT_R16G16B16A16_SFLOAT:
case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
case VK_FORMAT_R16_SINT: case VK_FORMAT_R16_SINT:
case VK_FORMAT_R16G16_SINT: case VK_FORMAT_R16G16_SINT:
case VK_FORMAT_R16G16B16A16_SINT: case VK_FORMAT_R16G16B16A16_SINT:
......
...@@ -924,13 +924,13 @@ void PixelRoutine::readPixel(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -924,13 +924,13 @@ void PixelRoutine::readPixel(int index, const Pointer<Byte> &cBuffer, const Int
{ {
Short4 c01; Short4 c01;
Short4 c23; Short4 c23;
Pointer<Byte> buffer; Pointer<Byte> buffer = cBuffer;
Pointer<Byte> buffer2; Pointer<Byte> buffer2;
switch(state.targetFormat[index]) switch(state.targetFormat[index])
{ {
case VK_FORMAT_A1R5G5B5_UNORM_PACK16: case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
buffer = cBuffer + 2 * x; buffer += 2 * x;
buffer2 = buffer + *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index])); buffer2 = buffer + *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
c01 = As<Short4>(Int2(*Pointer<Int>(buffer), *Pointer<Int>(buffer2))); c01 = As<Short4>(Int2(*Pointer<Int>(buffer), *Pointer<Int>(buffer2)));
...@@ -948,7 +948,7 @@ void PixelRoutine::readPixel(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -948,7 +948,7 @@ void PixelRoutine::readPixel(int index, const Pointer<Byte> &cBuffer, const Int
pixel.z |= As<Short4>(As<UShort4>(pixel.z) >> 10); pixel.z |= As<Short4>(As<UShort4>(pixel.z) >> 10);
break; break;
case VK_FORMAT_R5G6B5_UNORM_PACK16: case VK_FORMAT_R5G6B5_UNORM_PACK16:
buffer = cBuffer + 2 * x; buffer += 2 * x;
buffer2 = buffer + *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index])); buffer2 = buffer + *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
c01 = As<Short4>(Int2(*Pointer<Int>(buffer), *Pointer<Int>(buffer2))); c01 = As<Short4>(Int2(*Pointer<Int>(buffer), *Pointer<Int>(buffer2)));
...@@ -967,7 +967,7 @@ void PixelRoutine::readPixel(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -967,7 +967,7 @@ void PixelRoutine::readPixel(int index, const Pointer<Byte> &cBuffer, const Int
break; break;
case VK_FORMAT_B8G8R8A8_UNORM: case VK_FORMAT_B8G8R8A8_UNORM:
case VK_FORMAT_B8G8R8A8_SRGB: case VK_FORMAT_B8G8R8A8_SRGB:
buffer = cBuffer + 4 * x; buffer += 4 * x;
c01 = *Pointer<Short4>(buffer); c01 = *Pointer<Short4>(buffer);
buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index])); buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
c23 = *Pointer<Short4>(buffer); c23 = *Pointer<Short4>(buffer);
...@@ -987,7 +987,7 @@ void PixelRoutine::readPixel(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -987,7 +987,7 @@ void PixelRoutine::readPixel(int index, const Pointer<Byte> &cBuffer, const Int
break; break;
case VK_FORMAT_R8G8B8A8_UNORM: case VK_FORMAT_R8G8B8A8_UNORM:
case VK_FORMAT_R8G8B8A8_SRGB: case VK_FORMAT_R8G8B8A8_SRGB:
buffer = cBuffer + 4 * x; buffer += 4 * x;
c01 = *Pointer<Short4>(buffer); c01 = *Pointer<Short4>(buffer);
buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index])); buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
c23 = *Pointer<Short4>(buffer); c23 = *Pointer<Short4>(buffer);
...@@ -1006,7 +1006,7 @@ void PixelRoutine::readPixel(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -1006,7 +1006,7 @@ void PixelRoutine::readPixel(int index, const Pointer<Byte> &cBuffer, const Int
pixel.w = UnpackHigh(As<Byte8>(pixel.w), As<Byte8>(pixel.w)); pixel.w = UnpackHigh(As<Byte8>(pixel.w), As<Byte8>(pixel.w));
break; break;
case VK_FORMAT_R8_UNORM: case VK_FORMAT_R8_UNORM:
buffer = cBuffer + 1 * x; buffer += 1 * x;
pixel.x = Insert(pixel.x, *Pointer<Short>(buffer), 0); pixel.x = Insert(pixel.x, *Pointer<Short>(buffer), 0);
buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index])); buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
pixel.x = Insert(pixel.x, *Pointer<Short>(buffer), 1); pixel.x = Insert(pixel.x, *Pointer<Short>(buffer), 1);
...@@ -1016,7 +1016,7 @@ void PixelRoutine::readPixel(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -1016,7 +1016,7 @@ void PixelRoutine::readPixel(int index, const Pointer<Byte> &cBuffer, const Int
pixel.w = Short4(0xFFFFu); pixel.w = Short4(0xFFFFu);
break; break;
case VK_FORMAT_R8G8_UNORM: case VK_FORMAT_R8G8_UNORM:
buffer = cBuffer + 2 * x; buffer += 2 * x;
c01 = As<Short4>(Insert(As<Int2>(c01), *Pointer<Int>(buffer), 0)); c01 = As<Short4>(Insert(As<Int2>(c01), *Pointer<Int>(buffer), 0));
buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index])); buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
c01 = As<Short4>(Insert(As<Int2>(c01), *Pointer<Int>(buffer), 1)); c01 = As<Short4>(Insert(As<Int2>(c01), *Pointer<Int>(buffer), 1));
...@@ -1026,7 +1026,6 @@ void PixelRoutine::readPixel(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -1026,7 +1026,6 @@ void PixelRoutine::readPixel(int index, const Pointer<Byte> &cBuffer, const Int
pixel.w = Short4(0xFFFFu); pixel.w = Short4(0xFFFFu);
break; break;
case VK_FORMAT_R16G16B16A16_UNORM: case VK_FORMAT_R16G16B16A16_UNORM:
buffer = cBuffer;
pixel.x = *Pointer<Short4>(buffer + 8 * x); pixel.x = *Pointer<Short4>(buffer + 8 * x);
pixel.y = *Pointer<Short4>(buffer + 8 * x + 8); pixel.y = *Pointer<Short4>(buffer + 8 * x + 8);
buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index])); buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
...@@ -1035,7 +1034,6 @@ void PixelRoutine::readPixel(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -1035,7 +1034,6 @@ void PixelRoutine::readPixel(int index, const Pointer<Byte> &cBuffer, const Int
transpose4x4(pixel.x, pixel.y, pixel.z, pixel.w); transpose4x4(pixel.x, pixel.y, pixel.z, pixel.w);
break; break;
case VK_FORMAT_R16G16_UNORM: case VK_FORMAT_R16G16_UNORM:
buffer = cBuffer;
pixel.x = *Pointer<Short4>(buffer + 4 * x); pixel.x = *Pointer<Short4>(buffer + 4 * x);
buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index])); buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
pixel.y = *Pointer<Short4>(buffer + 4 * x); pixel.y = *Pointer<Short4>(buffer + 4 * x);
...@@ -1050,7 +1048,6 @@ void PixelRoutine::readPixel(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -1050,7 +1048,6 @@ void PixelRoutine::readPixel(int index, const Pointer<Byte> &cBuffer, const Int
break; break;
case VK_FORMAT_A2B10G10R10_UNORM_PACK32: case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
{ {
buffer = cBuffer;
Int4 v = Int4(0); Int4 v = Int4(0);
v = Insert(v, *Pointer<Int>(buffer + 4 * x), 0); v = Insert(v, *Pointer<Int>(buffer + 4 * x), 0);
v = Insert(v, *Pointer<Int>(buffer + 4 * x + 4), 1); v = Insert(v, *Pointer<Int>(buffer + 4 * x + 4), 1);
...@@ -1372,11 +1369,13 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -1372,11 +1369,13 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
xMask &= sMask; xMask &= sMask;
} }
Pointer<Byte> buffer = cBuffer;
switch(state.targetFormat[index]) switch(state.targetFormat[index])
{ {
case VK_FORMAT_A1R5G5B5_UNORM_PACK16: case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
{ {
Pointer<Byte> buffer = cBuffer + 2 * x; buffer += 2 * x;
Int value = *Pointer<Int>(buffer); Int value = *Pointer<Int>(buffer);
Int channelMask = *Pointer<Int>(constants + OFFSET(Constants,mask5551Q[bgraWriteMask & 0xF][0])); Int channelMask = *Pointer<Int>(constants + OFFSET(Constants,mask5551Q[bgraWriteMask & 0xF][0]));
...@@ -1403,7 +1402,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -1403,7 +1402,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
break; break;
case VK_FORMAT_R5G6B5_UNORM_PACK16: case VK_FORMAT_R5G6B5_UNORM_PACK16:
{ {
Pointer<Byte> buffer = cBuffer + 2 * x; buffer += 2 * x;
Int value = *Pointer<Int>(buffer); Int value = *Pointer<Int>(buffer);
Int channelMask = *Pointer<Int>(constants + OFFSET(Constants,mask565Q[bgraWriteMask & 0x7][0])); Int channelMask = *Pointer<Int>(constants + OFFSET(Constants,mask565Q[bgraWriteMask & 0x7][0]));
...@@ -1431,7 +1430,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -1431,7 +1430,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
case VK_FORMAT_B8G8R8A8_UNORM: case VK_FORMAT_B8G8R8A8_UNORM:
case VK_FORMAT_B8G8R8A8_SRGB: case VK_FORMAT_B8G8R8A8_SRGB:
{ {
Pointer<Byte> buffer = cBuffer + x * 4; buffer += x * 4;
Short4 value = *Pointer<Short4>(buffer); Short4 value = *Pointer<Short4>(buffer);
Short4 channelMask = *Pointer<Short4>(constants + OFFSET(Constants,maskB4Q[bgraWriteMask][0])); Short4 channelMask = *Pointer<Short4>(constants + OFFSET(Constants,maskB4Q[bgraWriteMask][0]));
...@@ -1458,7 +1457,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -1458,7 +1457,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
case VK_FORMAT_A8B8G8R8_UNORM_PACK32: case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
case VK_FORMAT_A8B8G8R8_SRGB_PACK32: case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
{ {
Pointer<Byte> buffer = cBuffer + x * 4; buffer += x * 4;
Short4 value = *Pointer<Short4>(buffer); Short4 value = *Pointer<Short4>(buffer);
Short4 channelMask = *Pointer<Short4>(constants + OFFSET(Constants,maskB4Q[rgbaWriteMask][0])); Short4 channelMask = *Pointer<Short4>(constants + OFFSET(Constants,maskB4Q[rgbaWriteMask][0]));
...@@ -1483,7 +1482,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -1483,7 +1482,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
case VK_FORMAT_R8G8_UNORM: case VK_FORMAT_R8G8_UNORM:
if((rgbaWriteMask & 0x00000003) != 0x0) if((rgbaWriteMask & 0x00000003) != 0x0)
{ {
Pointer<Byte> buffer = cBuffer + 2 * x; buffer += 2 * x;
Int2 value; Int2 value;
value = Insert(value, *Pointer<Int>(buffer), 0); value = Insert(value, *Pointer<Int>(buffer), 0);
Int pitch = *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index])); Int pitch = *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
...@@ -1508,7 +1507,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -1508,7 +1507,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
case VK_FORMAT_R8_UNORM: case VK_FORMAT_R8_UNORM:
if(rgbaWriteMask & 0x00000001) if(rgbaWriteMask & 0x00000001)
{ {
Pointer<Byte> buffer = cBuffer + 1 * x; buffer += 1 * x;
Short4 value; Short4 value;
value = Insert(value, *Pointer<Short>(buffer), 0); value = Insert(value, *Pointer<Short>(buffer), 0);
Int pitch = *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index])); Int pitch = *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
...@@ -1524,7 +1523,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -1524,7 +1523,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
break; break;
case VK_FORMAT_R16G16_UNORM: case VK_FORMAT_R16G16_UNORM:
{ {
Pointer<Byte> buffer = cBuffer + 4 * x; buffer += 4 * x;
Short4 value = *Pointer<Short4>(buffer); Short4 value = *Pointer<Short4>(buffer);
...@@ -1561,7 +1560,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -1561,7 +1560,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
break; break;
case VK_FORMAT_R16G16B16A16_UNORM: case VK_FORMAT_R16G16B16A16_UNORM:
{ {
Pointer<Byte> buffer = cBuffer + 8 * x; buffer += 8 * x;
{ {
Short4 value = *Pointer<Short4>(buffer); Short4 value = *Pointer<Short4>(buffer);
...@@ -1636,9 +1635,8 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -1636,9 +1635,8 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
break; break;
case VK_FORMAT_A2B10G10R10_UNORM_PACK32: case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
{ {
Pointer<Byte> buffer = cBuffer + 4 * x; buffer += 4 * x;
buffer = cBuffer + 4 * x;
Int2 value = *Pointer<Int2>(buffer, 16); Int2 value = *Pointer<Int2>(buffer, 16);
Int2 mergedMask = *Pointer<Int2>(constants + OFFSET(Constants, maskD01Q) + xMask * 8); Int2 mergedMask = *Pointer<Int2>(constants + OFFSET(Constants, maskD01Q) + xMask * 8);
if (rgbaWriteMask != 0xF) if (rgbaWriteMask != 0xF)
...@@ -1806,7 +1804,7 @@ void PixelRoutine::alphaBlend(int index, const Pointer<Byte> &cBuffer, Vector4f ...@@ -1806,7 +1804,7 @@ void PixelRoutine::alphaBlend(int index, const Pointer<Byte> &cBuffer, Vector4f
return; return;
} }
Pointer<Byte> buffer; Pointer<Byte> buffer = cBuffer;
// pixel holds four texel color values. // pixel holds four texel color values.
// Note: Despite the type being Vector4f, the colors may be stored as // Note: Despite the type being Vector4f, the colors may be stored as
...@@ -1834,7 +1832,6 @@ void PixelRoutine::alphaBlend(int index, const Pointer<Byte> &cBuffer, Vector4f ...@@ -1834,7 +1832,6 @@ void PixelRoutine::alphaBlend(int index, const Pointer<Byte> &cBuffer, Vector4f
case VK_FORMAT_R32_SINT: case VK_FORMAT_R32_SINT:
case VK_FORMAT_R32_UINT: case VK_FORMAT_R32_UINT:
case VK_FORMAT_R32_SFLOAT: case VK_FORMAT_R32_SFLOAT:
buffer = cBuffer;
// FIXME: movlps // FIXME: movlps
pixel.x.x = *Pointer<Float>(buffer + 4 * x + 0); pixel.x.x = *Pointer<Float>(buffer + 4 * x + 0);
pixel.x.y = *Pointer<Float>(buffer + 4 * x + 4); pixel.x.y = *Pointer<Float>(buffer + 4 * x + 4);
...@@ -1847,7 +1844,6 @@ void PixelRoutine::alphaBlend(int index, const Pointer<Byte> &cBuffer, Vector4f ...@@ -1847,7 +1844,6 @@ void PixelRoutine::alphaBlend(int index, const Pointer<Byte> &cBuffer, Vector4f
case VK_FORMAT_R32G32_SINT: case VK_FORMAT_R32G32_SINT:
case VK_FORMAT_R32G32_UINT: case VK_FORMAT_R32G32_UINT:
case VK_FORMAT_R32G32_SFLOAT: case VK_FORMAT_R32G32_SFLOAT:
buffer = cBuffer;
pixel.x = *Pointer<Float4>(buffer + 8 * x, 16); pixel.x = *Pointer<Float4>(buffer + 8 * x, 16);
buffer += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index])); buffer += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index]));
pixel.y = *Pointer<Float4>(buffer + 8 * x, 16); pixel.y = *Pointer<Float4>(buffer + 8 * x, 16);
...@@ -1860,7 +1856,6 @@ void PixelRoutine::alphaBlend(int index, const Pointer<Byte> &cBuffer, Vector4f ...@@ -1860,7 +1856,6 @@ void PixelRoutine::alphaBlend(int index, const Pointer<Byte> &cBuffer, Vector4f
case VK_FORMAT_R32G32B32A32_SFLOAT: case VK_FORMAT_R32G32B32A32_SFLOAT:
case VK_FORMAT_R32G32B32A32_SINT: case VK_FORMAT_R32G32B32A32_SINT:
case VK_FORMAT_R32G32B32A32_UINT: case VK_FORMAT_R32G32B32A32_UINT:
buffer = cBuffer;
pixel.x = *Pointer<Float4>(buffer + 16 * x, 16); pixel.x = *Pointer<Float4>(buffer + 16 * x, 16);
pixel.y = *Pointer<Float4>(buffer + 16 * x + 16, 16); pixel.y = *Pointer<Float4>(buffer + 16 * x + 16, 16);
buffer += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index])); buffer += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index]));
...@@ -1869,7 +1864,6 @@ void PixelRoutine::alphaBlend(int index, const Pointer<Byte> &cBuffer, Vector4f ...@@ -1869,7 +1864,6 @@ void PixelRoutine::alphaBlend(int index, const Pointer<Byte> &cBuffer, Vector4f
transpose4x4(pixel.x, pixel.y, pixel.z, pixel.w); transpose4x4(pixel.x, pixel.y, pixel.z, pixel.w);
break; break;
case VK_FORMAT_R16_SFLOAT: case VK_FORMAT_R16_SFLOAT:
buffer = cBuffer;
pixel.x.x = Float(*Pointer<Half>(buffer + 2 * x + 0)); pixel.x.x = Float(*Pointer<Half>(buffer + 2 * x + 0));
pixel.x.y = Float(*Pointer<Half>(buffer + 2 * x + 2)); pixel.x.y = Float(*Pointer<Half>(buffer + 2 * x + 2));
buffer += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index])); buffer += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index]));
...@@ -1878,7 +1872,6 @@ void PixelRoutine::alphaBlend(int index, const Pointer<Byte> &cBuffer, Vector4f ...@@ -1878,7 +1872,6 @@ void PixelRoutine::alphaBlend(int index, const Pointer<Byte> &cBuffer, Vector4f
pixel.y = pixel.z = pixel.w = one; pixel.y = pixel.z = pixel.w = one;
break; break;
case VK_FORMAT_R16G16_SFLOAT: case VK_FORMAT_R16G16_SFLOAT:
buffer = cBuffer;
pixel.x.x = Float(*Pointer<Half>(buffer + 4 * x + 0)); pixel.x.x = Float(*Pointer<Half>(buffer + 4 * x + 0));
pixel.y.x = Float(*Pointer<Half>(buffer + 4 * x + 2)); pixel.y.x = Float(*Pointer<Half>(buffer + 4 * x + 2));
pixel.x.y = Float(*Pointer<Half>(buffer + 4 * x + 4)); pixel.x.y = Float(*Pointer<Half>(buffer + 4 * x + 4));
...@@ -1891,7 +1884,6 @@ void PixelRoutine::alphaBlend(int index, const Pointer<Byte> &cBuffer, Vector4f ...@@ -1891,7 +1884,6 @@ void PixelRoutine::alphaBlend(int index, const Pointer<Byte> &cBuffer, Vector4f
pixel.z = pixel.w = one; pixel.z = pixel.w = one;
break; break;
case VK_FORMAT_R16G16B16A16_SFLOAT: case VK_FORMAT_R16G16B16A16_SFLOAT:
buffer = cBuffer;
pixel.x.x = Float(*Pointer<Half>(buffer + 8 * x + 0x0)); pixel.x.x = Float(*Pointer<Half>(buffer + 8 * x + 0x0));
pixel.y.x = Float(*Pointer<Half>(buffer + 8 * x + 0x2)); pixel.y.x = Float(*Pointer<Half>(buffer + 8 * x + 0x2));
pixel.z.x = Float(*Pointer<Half>(buffer + 8 * x + 0x4)); pixel.z.x = Float(*Pointer<Half>(buffer + 8 * x + 0x4));
...@@ -1910,6 +1902,14 @@ void PixelRoutine::alphaBlend(int index, const Pointer<Byte> &cBuffer, Vector4f ...@@ -1910,6 +1902,14 @@ void PixelRoutine::alphaBlend(int index, const Pointer<Byte> &cBuffer, Vector4f
pixel.z.w = Float(*Pointer<Half>(buffer + 8 * x + 0xc)); pixel.z.w = Float(*Pointer<Half>(buffer + 8 * x + 0xc));
pixel.w.w = Float(*Pointer<Half>(buffer + 8 * x + 0xe)); pixel.w.w = Float(*Pointer<Half>(buffer + 8 * x + 0xe));
break; break;
case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
pixel.x = r11g11b10Unpack(*Pointer<UInt>(buffer + 4 * x + 0));
pixel.y = r11g11b10Unpack(*Pointer<UInt>(buffer + 4 * x + 4));
buffer += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index]));
pixel.z = r11g11b10Unpack(*Pointer<UInt>(buffer + 4 * x + 0));
pixel.w = r11g11b10Unpack(*Pointer<UInt>(buffer + 4 * x + 4));
transpose4x4(pixel.x, pixel.y, pixel.z, pixel.w);
break;
default: default:
UNIMPLEMENTED("VkFormat: %d", int(state.targetFormat[index])); UNIMPLEMENTED("VkFormat: %d", int(state.targetFormat[index]));
} }
...@@ -2039,6 +2039,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -2039,6 +2039,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
oC.y = oC.z; oC.y = oC.z;
break; break;
case VK_FORMAT_R16G16B16A16_SFLOAT: case VK_FORMAT_R16G16B16A16_SFLOAT:
case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
case VK_FORMAT_R32G32B32A32_SFLOAT: case VK_FORMAT_R32G32B32A32_SFLOAT:
case VK_FORMAT_R32G32B32A32_SINT: case VK_FORMAT_R32G32B32A32_SINT:
case VK_FORMAT_R32G32B32A32_UINT: case VK_FORMAT_R32G32B32A32_UINT:
...@@ -2074,7 +2075,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -2074,7 +2075,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
auto targetFormat = state.targetFormat[index]; auto targetFormat = state.targetFormat[index];
Pointer<Byte> buffer; Pointer<Byte> buffer = cBuffer;
Float4 value; Float4 value;
switch(targetFormat) switch(targetFormat)
...@@ -2084,7 +2085,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -2084,7 +2085,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
case VK_FORMAT_R32_UINT: case VK_FORMAT_R32_UINT:
if(rgbaWriteMask & 0x00000001) if(rgbaWriteMask & 0x00000001)
{ {
buffer = cBuffer + 4 * x; buffer += 4 * x;
// FIXME: movlps // FIXME: movlps
value.x = *Pointer<Float>(buffer + 0); value.x = *Pointer<Float>(buffer + 0);
...@@ -2114,7 +2115,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -2114,7 +2115,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
case VK_FORMAT_R16_SFLOAT: case VK_FORMAT_R16_SFLOAT:
if(rgbaWriteMask & 0x00000001) if(rgbaWriteMask & 0x00000001)
{ {
buffer = cBuffer + 2 * x; buffer += 2 * x;
value = Insert(value, Float(*Pointer<Half>(buffer + 0)), 0); value = Insert(value, Float(*Pointer<Half>(buffer + 0)), 0);
value = Insert(value, Float(*Pointer<Half>(buffer + 2)), 1); value = Insert(value, Float(*Pointer<Half>(buffer + 2)), 1);
...@@ -2141,7 +2142,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -2141,7 +2142,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
case VK_FORMAT_R16_UINT: case VK_FORMAT_R16_UINT:
if(rgbaWriteMask & 0x00000001) if(rgbaWriteMask & 0x00000001)
{ {
buffer = cBuffer + 2 * x; buffer += 2 * x;
UShort4 xyzw; UShort4 xyzw;
xyzw = As<UShort4>(Insert(As<Int2>(xyzw), *Pointer<Int>(buffer), 0)); xyzw = As<UShort4>(Insert(As<Int2>(xyzw), *Pointer<Int>(buffer), 0));
...@@ -2189,7 +2190,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -2189,7 +2190,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
case VK_FORMAT_R8_UINT: case VK_FORMAT_R8_UINT:
if(rgbaWriteMask & 0x00000001) if(rgbaWriteMask & 0x00000001)
{ {
buffer = cBuffer + x; buffer += x;
UInt xyzw, packedCol; UInt xyzw, packedCol;
...@@ -2219,7 +2220,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -2219,7 +2220,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
case VK_FORMAT_R32G32_SFLOAT: case VK_FORMAT_R32G32_SFLOAT:
case VK_FORMAT_R32G32_SINT: case VK_FORMAT_R32G32_SINT:
case VK_FORMAT_R32G32_UINT: case VK_FORMAT_R32G32_UINT:
buffer = cBuffer + 8 * x; buffer += 8 * x;
value = *Pointer<Float4>(buffer); value = *Pointer<Float4>(buffer);
...@@ -2258,7 +2259,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -2258,7 +2259,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
case VK_FORMAT_R16G16_SFLOAT: case VK_FORMAT_R16G16_SFLOAT:
if((rgbaWriteMask & 0x00000003) != 0x0) if((rgbaWriteMask & 0x00000003) != 0x0)
{ {
buffer = cBuffer + 4 * x; buffer += 4 * x;
UInt2 rgbaMask; UInt2 rgbaMask;
UInt2 packedCol; UInt2 packedCol;
...@@ -2292,7 +2293,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -2292,7 +2293,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
case VK_FORMAT_R16G16_UINT: case VK_FORMAT_R16G16_UINT:
if((rgbaWriteMask & 0x00000003) != 0x0) if((rgbaWriteMask & 0x00000003) != 0x0)
{ {
buffer = cBuffer + 4 * x; buffer += 4 * x;
UInt2 rgbaMask; UInt2 rgbaMask;
UShort4 packedCol = UShort4(As<Int4>(oC.x)); UShort4 packedCol = UShort4(As<Int4>(oC.x));
...@@ -2322,7 +2323,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -2322,7 +2323,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
case VK_FORMAT_R8G8_UINT: case VK_FORMAT_R8G8_UINT:
if((rgbaWriteMask & 0x00000003) != 0x0) if((rgbaWriteMask & 0x00000003) != 0x0)
{ {
buffer = cBuffer + 2 * x; buffer += 2 * x;
Int2 xyzw, packedCol; Int2 xyzw, packedCol;
...@@ -2357,7 +2358,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -2357,7 +2358,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
case VK_FORMAT_R32G32B32A32_SFLOAT: case VK_FORMAT_R32G32B32A32_SFLOAT:
case VK_FORMAT_R32G32B32A32_SINT: case VK_FORMAT_R32G32B32A32_SINT:
case VK_FORMAT_R32G32B32A32_UINT: case VK_FORMAT_R32G32B32A32_UINT:
buffer = cBuffer + 16 * x; buffer += 16 * x;
{ {
value = *Pointer<Float4>(buffer, 16); value = *Pointer<Float4>(buffer, 16);
...@@ -2432,7 +2433,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -2432,7 +2433,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
case VK_FORMAT_R16G16B16A16_SFLOAT: case VK_FORMAT_R16G16B16A16_SFLOAT:
if((rgbaWriteMask & 0x0000000F) != 0x0) if((rgbaWriteMask & 0x0000000F) != 0x0)
{ {
buffer = cBuffer + 8 * x; buffer += 8 * x;
UInt4 rgbaMask; UInt4 rgbaMask;
UInt4 value = *Pointer<UInt4>(buffer); UInt4 value = *Pointer<UInt4>(buffer);
...@@ -2465,11 +2466,31 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -2465,11 +2466,31 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
*Pointer<UInt4>(buffer) = (packedCol & mergedMask) | (As<UInt4>(value) & ~mergedMask); *Pointer<UInt4>(buffer) = (packedCol & mergedMask) | (As<UInt4>(value) & ~mergedMask);
} }
break; break;
case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
if((rgbaWriteMask & 0x7) != 0x0)
{
buffer += 4 * x;
unsigned int mask = ((rgbaWriteMask & 0x1) ? 0x000007FF : 0) |
((rgbaWriteMask & 0x2) ? 0x003FF800 : 0) |
((rgbaWriteMask & 0x4) ? 0xFFC00000 : 0);
UInt2 mergedMask(mask, mask);
UInt2 value;
value = Insert(value, r11g11b10Pack(oC.x), 0);
value = Insert(value, r11g11b10Pack(oC.y), 1);
*Pointer<UInt2>(buffer) = (value & mergedMask) | ((*Pointer<UInt2>(buffer)) & ~mergedMask);
buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
value = Insert(value, r11g11b10Pack(oC.z), 0);
value = Insert(value, r11g11b10Pack(oC.w), 1);
*Pointer<UInt2>(buffer) = (value & mergedMask) | ((*Pointer<UInt2>(buffer)) & ~mergedMask);
}
break;
case VK_FORMAT_R16G16B16A16_SINT: case VK_FORMAT_R16G16B16A16_SINT:
case VK_FORMAT_R16G16B16A16_UINT: case VK_FORMAT_R16G16B16A16_UINT:
if((rgbaWriteMask & 0x0000000F) != 0x0) if((rgbaWriteMask & 0x0000000F) != 0x0)
{ {
buffer = cBuffer + 8 * x; buffer += 8 * x;
UInt4 rgbaMask; UInt4 rgbaMask;
UShort8 value = *Pointer<UShort8>(buffer); UShort8 value = *Pointer<UShort8>(buffer);
...@@ -2503,7 +2524,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -2503,7 +2524,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
{ {
UInt2 value, packedCol, mergedMask; UInt2 value, packedCol, mergedMask;
buffer = cBuffer + 4 * x; buffer += 4 * x;
bool isSigned = targetFormat == VK_FORMAT_R8G8B8A8_SINT || targetFormat == VK_FORMAT_A8B8G8R8_SINT_PACK32; bool isSigned = targetFormat == VK_FORMAT_R8G8B8A8_SINT || targetFormat == VK_FORMAT_A8B8G8R8_SINT_PACK32;
...@@ -2551,7 +2572,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int ...@@ -2551,7 +2572,7 @@ void PixelRoutine::writeColor(int index, const Pointer<Byte> &cBuffer, const Int
((As<Int4>(oC.y) & Int4(0x3ff)) << 10) | ((As<Int4>(oC.y) & Int4(0x3ff)) << 10) |
((As<Int4>(oC.x) & Int4(0x3ff))); ((As<Int4>(oC.x) & Int4(0x3ff)));
buffer = cBuffer + 4 * x; buffer += 4 * x;
value = *Pointer<Int2>(buffer, 16); value = *Pointer<Int2>(buffer, 16);
mergedMask = *Pointer<Int2>(constants + OFFSET(Constants, maskD01Q) + xMask * 8); mergedMask = *Pointer<Int2>(constants + OFFSET(Constants, maskD01Q) + xMask * 8);
if (rgbaWriteMask != 0xF) if (rgbaWriteMask != 0xF)
......
...@@ -546,27 +546,72 @@ void transpose4xN(Float4 &row0, Float4 &row1, Float4 &row2, Float4 &row3, int N) ...@@ -546,27 +546,72 @@ void transpose4xN(Float4 &row0, Float4 &row1, Float4 &row2, Float4 &row3, int N)
} }
} }
UInt4 halfToFloatBits(UInt4 halfBits) SIMD::UInt halfToFloatBits(SIMD::UInt halfBits)
{ {
auto magic = UInt4(126 << 23); auto magic = SIMD::UInt(126 << 23);
auto sign16 = halfBits & UInt4(0x8000); auto sign16 = halfBits & SIMD::UInt(0x8000);
auto man16 = halfBits & UInt4(0x3FF); auto man16 = halfBits & SIMD::UInt(0x03FF);
auto exp16 = halfBits & UInt4(0x7C00); auto exp16 = halfBits & SIMD::UInt(0x7C00);
auto isDnormOrZero = CmpEQ(exp16, UInt4(0)); auto isDnormOrZero = CmpEQ(exp16, SIMD::UInt(0));
auto isInfOrNaN = CmpEQ(exp16, UInt4(0x7C00)); auto isInfOrNaN = CmpEQ(exp16, SIMD::UInt(0x7C00));
auto sign32 = sign16 << 16; auto sign32 = sign16 << 16;
auto man32 = man16 << 13; auto man32 = man16 << 13;
auto exp32 = (exp16 + UInt4(0x1C000)) << 13; auto exp32 = (exp16 + SIMD::UInt(0x1C000)) << 13;
auto norm32 = (man32 | exp32) | (isInfOrNaN & UInt4(0x7F800000)); auto norm32 = (man32 | exp32) | (isInfOrNaN & SIMD::UInt(0x7F800000));
auto denorm32 = As<UInt4>(As<Float4>(magic + man16) - As<Float4>(magic)); auto denorm32 = As<SIMD::UInt>(As<SIMD::Float>(magic + man16) - As<SIMD::Float>(magic));
return sign32 | (norm32 & ~isDnormOrZero) | (denorm32 & isDnormOrZero); return sign32 | (norm32 & ~isDnormOrZero) | (denorm32 & isDnormOrZero);
} }
SIMD::UInt floatToHalfBits(SIMD::UInt floatBits, bool storeInUpperBits)
{
static const uint32_t mask_sign = 0x80000000u;
static const uint32_t mask_round = ~0xfffu;
static const uint32_t c_f32infty = 255 << 23;
static const uint32_t c_magic = 15 << 23;
static const uint32_t c_nanbit = 0x200;
static const uint32_t c_infty_as_fp16 = 0x7c00;
static const uint32_t c_clamp = (31 << 23) - 0x1000;
SIMD::UInt justsign = SIMD::UInt(mask_sign) & floatBits;
SIMD::UInt absf = floatBits ^ justsign;
SIMD::UInt b_isnormal = CmpNLE(SIMD::UInt(c_f32infty), absf);
// Note: this version doesn't round to the nearest even in case of a tie as defined by IEEE 754-2008, it rounds to +inf
// instead of nearest even, since that's fine for GLSL ES 3.0's needs (see section 2.1.1 Floating-Point Computation)
SIMD::UInt joined = ((((As<SIMD::UInt>(Min(As<SIMD::Float>(absf & SIMD::UInt(mask_round)) * As<SIMD::Float>(SIMD::UInt(c_magic)),
As<SIMD::Float>(SIMD::UInt(c_clamp))))) - SIMD::UInt(mask_round)) >> 13) & b_isnormal) |
((b_isnormal ^ SIMD::UInt(0xFFFFFFFF)) &
((CmpNLE(absf, SIMD::UInt(c_f32infty)) & SIMD::UInt(c_nanbit)) | SIMD::UInt(c_infty_as_fp16)));
return storeInUpperBits ? ((joined << 16) | justsign) : joined | (justsign >> 16);
}
sw::SIMD::Float r11g11b10Unpack(UInt r11g11b10bits)
{
// 10 (or 11) bit float formats are unsigned formats with a 5 bit exponent and a 5 (or 6) bit mantissa.
// Since the Half float format also has a 5 bit exponent, we can convert these formats to half by
// copy/pasting the bits so the the exponent bits and top mantissa bits are aligned to the half format.
// In this case, we have:
// MSB | B B B B B B B B B B G G G G G G G G G G G R R R R R R R R R R R | LSB
SIMD::UInt halfBits;
halfBits = Insert(halfBits, (r11g11b10bits & UInt(0x000007FFu)) << 4, 0);
halfBits = Insert(halfBits, (r11g11b10bits & UInt(0x003FF800u)) >> 7, 1);
halfBits = Insert(halfBits, (r11g11b10bits & UInt(0xFFC00000u)) >> 17, 2);
halfBits = Insert(halfBits, UInt(0x00003C00u), 3);
return As<sw::SIMD::Float>(halfToFloatBits(halfBits));
}
UInt r11g11b10Pack(sw::SIMD::Float &value)
{
SIMD::UInt halfBits = floatToHalfBits(As<SIMD::UInt>(value), true) &
SIMD::UInt(0x7FF00000, 0x7FF00000, 0x7FE00000, 0);
return (UInt(halfBits.x) >> 20) | (UInt(halfBits.y) >> 9) | (UInt(halfBits.z) << 1);
}
rr::RValue<rr::Bool> AnyTrue(rr::RValue<sw::SIMD::Int> const &ints) rr::RValue<rr::Bool> AnyTrue(rr::RValue<sw::SIMD::Int> const &ints)
{ {
......
...@@ -190,7 +190,10 @@ void transpose4x1(Float4 &row0, Float4 &row1, Float4 &row2, Float4 &row3); ...@@ -190,7 +190,10 @@ void transpose4x1(Float4 &row0, Float4 &row1, Float4 &row2, Float4 &row3);
void transpose2x4(Float4 &row0, Float4 &row1, Float4 &row2, Float4 &row3); void transpose2x4(Float4 &row0, Float4 &row1, Float4 &row2, Float4 &row3);
void transpose4xN(Float4 &row0, Float4 &row1, Float4 &row2, Float4 &row3, int N); void transpose4xN(Float4 &row0, Float4 &row1, Float4 &row2, Float4 &row3, int N);
UInt4 halfToFloatBits(UInt4 halfBits); sw::SIMD::UInt halfToFloatBits(sw::SIMD::UInt halfBits);
sw::SIMD::UInt floatToHalfBits(sw::SIMD::UInt floatBits, bool storeInUpperBits);
sw::SIMD::Float r11g11b10Unpack(UInt r11g11b10bits);
UInt r11g11b10Pack(sw::SIMD::Float &value);
rr::RValue<rr::Bool> AnyTrue(rr::RValue<sw::SIMD::Int> const &ints); rr::RValue<rr::Bool> AnyTrue(rr::RValue<sw::SIMD::Int> const &ints);
......
...@@ -1087,8 +1087,6 @@ private: ...@@ -1087,8 +1087,6 @@ private:
// Helper as we often need to take dot products as part of doing other things. // Helper as we often need to take dot products as part of doing other things.
SIMD::Float Dot(unsigned numComponents, GenericValue const & x, GenericValue const & y) const; SIMD::Float Dot(unsigned numComponents, GenericValue const & x, GenericValue const & y) const;
SIMD::UInt FloatToHalfBits(SIMD::UInt floatBits, bool storeInUpperBits) const;
// Splits x into a floating-point significand in the range [0.5, 1.0) // Splits x into a floating-point significand in the range [0.5, 1.0)
// and an integral exponent of two, such that: // and an integral exponent of two, such that:
// x = significand * 2^exponent // x = significand * 2^exponent
......
...@@ -544,30 +544,6 @@ SIMD::Float SpirvShader::Dot(unsigned numComponents, GenericValue const & x, Gen ...@@ -544,30 +544,6 @@ SIMD::Float SpirvShader::Dot(unsigned numComponents, GenericValue const & x, Gen
return d; return d;
} }
SIMD::UInt SpirvShader::FloatToHalfBits(SIMD::UInt floatBits, bool storeInUpperBits) const
{
static const uint32_t mask_sign = 0x80000000u;
static const uint32_t mask_round = ~0xfffu;
static const uint32_t c_f32infty = 255 << 23;
static const uint32_t c_magic = 15 << 23;
static const uint32_t c_nanbit = 0x200;
static const uint32_t c_infty_as_fp16 = 0x7c00;
static const uint32_t c_clamp = (31 << 23) - 0x1000;
SIMD::UInt justsign = SIMD::UInt(mask_sign) & floatBits;
SIMD::UInt absf = floatBits ^ justsign;
SIMD::UInt b_isnormal = CmpNLE(SIMD::UInt(c_f32infty), absf);
// Note: this version doesn't round to the nearest even in case of a tie as defined by IEEE 754-2008, it rounds to +inf
// instead of nearest even, since that's fine for GLSL ES 3.0's needs (see section 2.1.1 Floating-Point Computation)
SIMD::UInt joined = ((((As<SIMD::UInt>(Min(As<SIMD::Float>(absf & SIMD::UInt(mask_round)) * As<SIMD::Float>(SIMD::UInt(c_magic)),
As<SIMD::Float>(SIMD::UInt(c_clamp))))) - SIMD::UInt(mask_round)) >> 13) & b_isnormal) |
((b_isnormal ^ SIMD::UInt(0xFFFFFFFF)) & ((CmpNLE(absf, SIMD::UInt(c_f32infty)) & SIMD::UInt(c_nanbit)) |
SIMD::UInt(c_infty_as_fp16)));
return storeInUpperBits ? ((joined << 16) | justsign) : joined | (justsign >> 16);
}
std::pair<SIMD::Float, SIMD::Int> SpirvShader::Frexp(RValue<SIMD::Float> val) const std::pair<SIMD::Float, SIMD::Int> SpirvShader::Frexp(RValue<SIMD::Float> val) const
{ {
// Assumes IEEE 754 // Assumes IEEE 754
......
...@@ -431,7 +431,7 @@ SpirvShader::EmitResult SpirvShader::EmitExtendedInstruction(InsnIterator insn, ...@@ -431,7 +431,7 @@ SpirvShader::EmitResult SpirvShader::EmitExtendedInstruction(InsnIterator insn,
case GLSLstd450PackHalf2x16: case GLSLstd450PackHalf2x16:
{ {
auto val = GenericValue(this, state, insn.word(5)); auto val = GenericValue(this, state, insn.word(5));
dst.move(0, FloatToHalfBits(val.UInt(0), false) | FloatToHalfBits(val.UInt(1), true)); dst.move(0, floatToHalfBits(val.UInt(0), false) | floatToHalfBits(val.UInt(1), true));
break; break;
} }
case GLSLstd450UnpackSnorm4x8: case GLSLstd450UnpackSnorm4x8:
......
...@@ -900,8 +900,8 @@ SpirvShader::EmitResult SpirvShader::EmitImageWrite(InsnIterator insn, EmitState ...@@ -900,8 +900,8 @@ SpirvShader::EmitResult SpirvShader::EmitImageWrite(InsnIterator insn, EmitState
break; break;
case spv::ImageFormatRgba16f: case spv::ImageFormatRgba16f:
texelSize = 8; texelSize = 8;
packed[0] = FloatToHalfBits(texel.UInt(0), false) | FloatToHalfBits(texel.UInt(1), true); packed[0] = floatToHalfBits(texel.UInt(0), false) | floatToHalfBits(texel.UInt(1), true);
packed[1] = FloatToHalfBits(texel.UInt(2), false) | FloatToHalfBits(texel.UInt(3), true); packed[1] = floatToHalfBits(texel.UInt(2), false) | floatToHalfBits(texel.UInt(3), true);
numPackedElements = 2; numPackedElements = 2;
break; break;
case spv::ImageFormatRgba16i: case spv::ImageFormatRgba16i:
......
...@@ -630,6 +630,7 @@ void PhysicalDevice::getFormatProperties(Format format, VkFormatProperties* pFor ...@@ -630,6 +630,7 @@ void PhysicalDevice::getFormatProperties(Format format, VkFormatProperties* pFor
case VK_FORMAT_R32G32B32A32_UINT: case VK_FORMAT_R32G32B32A32_UINT:
case VK_FORMAT_R32G32B32A32_SINT: case VK_FORMAT_R32G32B32A32_SINT:
case VK_FORMAT_R32G32B32A32_SFLOAT: case VK_FORMAT_R32G32B32A32_SFLOAT:
case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
pFormatProperties->optimalTilingFeatures |= pFormatProperties->optimalTilingFeatures |=
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
VK_FORMAT_FEATURE_BLIT_DST_BIT; VK_FORMAT_FEATURE_BLIT_DST_BIT;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment