From d2d86b5726f74d8a14ae030aa7559e431e412ef4 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 20 Mar 2017 13:02:20 +0000 Subject: [PATCH] Add 'floateleven' buffer format for R11G11B10 packed data, fix unpacking --- docs/window/buffer_viewer.rst | 1 + qrenderdoc/Code/FormatElement.cpp | 61 ++++++++++++++++--- qrenderdoc/Widgets/BufferFormatSpecifier.ui | 2 +- .../D3D11PipelineStateViewer.cpp | 19 ++++-- .../D3D12PipelineStateViewer.cpp | 19 ++++-- renderdocui/Code/FormatElement.cs | 58 +++++++++++++++--- .../Controls/BufferFormatSpecifier.resx | 2 +- .../PipelineState/D3D11PipelineStateViewer.cs | 13 +++- .../PipelineState/D3D12PipelineStateViewer.cs | 13 +++- 9 files changed, 150 insertions(+), 38 deletions(-) diff --git a/docs/window/buffer_viewer.rst b/docs/window/buffer_viewer.rst index 984b82a82..933dcf586 100644 --- a/docs/window/buffer_viewer.rst +++ b/docs/window/buffer_viewer.rst @@ -103,6 +103,7 @@ There are also some non-hlsl types for displaying other formats which don't have * ``snormf`` - 32bit signed normalised value * ``uintten`` - 4 component unsigned integer format, packed as 10:10:10:2 * ``unormten`` - 4 component unsigned normalised format, packed as 10:10:10:2 +* ``floateleven`` - 3 component floating point format, packed as 11:11:10 * ``xuint`` - hex-formatted 32bit integer * ``xshort`` - hex-formatted 16bit integer * ``xbyte`` - hex-formatted 8bit integer diff --git a/qrenderdoc/Code/FormatElement.cpp b/qrenderdoc/Code/FormatElement.cpp index 1ceae5a80..e5936f10b 100644 --- a/qrenderdoc/Code/FormatElement.cpp +++ b/qrenderdoc/Code/FormatElement.cpp @@ -149,6 +149,7 @@ QList FormatElement::ParseFormatString(const QString &formatStrin "^(row_major\\s+)?" // row_major matrix "(" "uintten|unormten" + "|floateleven" "|unormh|unormb" "|snormh|snormb" "|bool" // bool is stored as 4-byte int @@ -337,6 +338,14 @@ QList FormatElement::ParseFormatString(const QString &formatStrin fmt.special = true; fmt.specialFormat = eSpecial_R10G10B10A2; } + else if(basetype == "floateleven") + { + fmt.compType = eCompType_Float; + fmt.compCount = 3 * count; + fmt.compByteWidth = 1; + fmt.special = true; + fmt.specialFormat = eSpecial_R11G11B10; + } else { errors = "Unrecognised basic type on line:\n" + line; @@ -585,16 +594,50 @@ QVariantList FormatElement::GetVariants(const byte *&data, const byte *end) cons { uint32_t packed = readObj(data, end, ok); - uint32_t xMantissa = ((packed >> 0) & 0x3f); - uint32_t xExponent = ((packed >> 6) & 0x1f); - uint32_t yMantissa = ((packed >> 11) & 0x3f); - uint32_t yExponent = ((packed >> 17) & 0x1f); - uint32_t zMantissa = ((packed >> 22) & 0x1f); - uint32_t zExponent = ((packed >> 27) & 0x1f); + uint32_t mantissas[] = { + (packed >> 0) & 0x3f, (packed >> 11) & 0x3f, (packed >> 22) & 0x1f, + }; + int32_t exponents[] = { + int32_t(packed >> 6) & 0x1f, int32_t(packed >> 17) & 0x1f, int32_t(packed >> 27) & 0x1f, + }; + static const uint32_t leadbit[] = { + 0x40, 0x40, 0x20, + }; - ret.push_back(((float)(xMantissa) / 64.0f) * qPow(2.0f, (float)xExponent - 15.0f)); - ret.push_back(((float)(yMantissa) / 32.0f) * qPow(2.0f, (float)yExponent - 15.0f)); - ret.push_back(((float)(zMantissa) / 32.0f) * qPow(2.0f, (float)zExponent - 15.0f)); + for(int i = 0; i < 3; i++) + { + if(mantissas[i] == 0 && exponents[i] == 0) + { + ret.push_back((float)0.0f); + } + else + { + if(exponents[i] == 0x1f) + { + // no sign bit, can't be negative infinity + if(mantissas[i] == 0) + ret.push_back((float)qInf()); + else + ret.push_back((float)qQNaN()); + } + else if(exponents[i] != 0) + { + // normal value, add leading bit + uint32_t combined = leadbit[i] | mantissas[i]; + + // calculate value + ret.push_back(((float)combined / (float)leadbit[i]) * + qPow(2.0f, (float)exponents[i] - 15.0f)); + } + else if(exponents[i] == 0) + { + // we know xMantissa isn't 0 also, or it would have been caught above so + // this is a subnormal value, pretend exponent is 1 and don't add leading bit + + ret.push_back(((float)mantissas[i] / (float)leadbit[i]) * qPow(2.0f, (float)1.0f - 15.0f)); + } + } + } } else { diff --git a/qrenderdoc/Widgets/BufferFormatSpecifier.ui b/qrenderdoc/Widgets/BufferFormatSpecifier.ui index 461ea1a9b..3d4ee4918 100644 --- a/qrenderdoc/Widgets/BufferFormatSpecifier.ui +++ b/qrenderdoc/Widgets/BufferFormatSpecifier.ui @@ -82,7 +82,7 @@ Basic types accepted: bool, byte, short, int, half, float, double. Unsigned integer types: ubyte, ushort, uint Hex-formatted integer types: xbyte, xshort, xint -Additionally special formats: unorm[hb] (half, byte) and snorm[hb], and uintten/unormten (10:10:10:2 packing) +Additionally special formats: unorm[hb] (half, byte) and snorm[hb], uintten/unormten (10:10:10:2 packing), floateleven (11:11:10F packing) Vectors (e.g. float4), matrices ([row_major] half3x4) and arrays (float[16]) are supported. diff --git a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp index 64d76bf38..da57dffc5 100644 --- a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp @@ -1834,14 +1834,21 @@ void D3D11PipelineStateViewer::resource_itemActivated(QTreeWidgetItem *item, int else { const ResourceFormat &fmt = view.res.Format; - if(fmt.special && fmt.specialFormat == eSpecial_R10G10B10A2) + if(fmt.special) { - if(fmt.compType == eCompType_UInt) - format = "uintten"; - if(fmt.compType == eCompType_UNorm) - format = "unormten"; + if(fmt.specialFormat == eSpecial_R10G10B10A2) + { + if(fmt.compType == eCompType_UInt) + format = "uintten"; + if(fmt.compType == eCompType_UNorm) + format = "unormten"; + } + else if(fmt.specialFormat == eSpecial_R11G11B10) + { + format = "floateleven"; + } } - else if(!fmt.special) + else { switch(fmt.compByteWidth) { diff --git a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp index 4c91456f0..cc183e19b 100644 --- a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp @@ -1822,14 +1822,21 @@ void D3D12PipelineStateViewer::resource_itemActivated(QTreeWidgetItem *item, int else { const ResourceFormat &fmt = view.res.Format; - if(fmt.special && fmt.specialFormat == eSpecial_R10G10B10A2) + if(fmt.special) { - if(fmt.compType == eCompType_UInt) - format = "uintten"; - if(fmt.compType == eCompType_UNorm) - format = "unormten"; + if(fmt.specialFormat == eSpecial_R10G10B10A2) + { + if(fmt.compType == eCompType_UInt) + format = "uintten"; + if(fmt.compType == eCompType_UNorm) + format = "unormten"; + } + else if(fmt.specialFormat == eSpecial_R11G11B10) + { + format = "floateleven"; + } } - else if(!fmt.special) + else { switch(fmt.compByteWidth) { diff --git a/renderdocui/Code/FormatElement.cs b/renderdocui/Code/FormatElement.cs index 2870404eb..6e97b4938 100644 --- a/renderdocui/Code/FormatElement.cs +++ b/renderdocui/Code/FormatElement.cs @@ -258,16 +258,49 @@ namespace renderdocui.Code { uint packed = read.ReadUInt32(); - uint xMantissa = ((packed >> 0) & 0x3f); - uint xExponent = ((packed >> 6) & 0x1f); - uint yMantissa = ((packed >> 11) & 0x3f); - uint yExponent = ((packed >> 17) & 0x1f); - uint zMantissa = ((packed >> 22) & 0x1f); - uint zExponent = ((packed >> 27) & 0x1f); + uint[] mantissas = new uint[] { + (packed >> 0) & 0x3f, (packed >> 11) & 0x3f, (packed >> 22) & 0x1f, + }; + uint[] leadbit = new uint[] { + 0x40, 0x40, 0x20, + }; + int[] exponents = new int[]{ + (int)(packed >> 6) & 0x1f, (int)(packed >> 17) & 0x1f, (int)(packed >> 27) & 0x1f, + }; - ret.Add(((float)(xMantissa) / 64.0f) * Math.Pow(2.0f, (float)xExponent - 15.0f)); - ret.Add(((float)(yMantissa) / 32.0f) * Math.Pow(2.0f, (float)yExponent - 15.0f)); - ret.Add(((float)(zMantissa) / 32.0f) * Math.Pow(2.0f, (float)zExponent - 15.0f)); + for (int i = 0; i < 3; i++) + { + if (mantissas[i] == 0 && exponents[i] == 0) + { + ret.Add((float)0.0f); + } + else + { + if (exponents[i] == 0x1f) + { + // no sign bit, can't be negative infinity + if (mantissas[i] == 0) + ret.Add(float.PositiveInfinity); + else + ret.Add(float.NaN); + } + else if (exponents[i] != 0) + { + // normal value, add leading bit + uint combined = leadbit[i] | mantissas[i]; + + // calculate value + ret.Add(((float)combined / (float)leadbit[i]) * Math.Pow(2.0f, (float)exponents[i] - 15.0f)); + } + else if (exponents[i] == 0) + { + // we know xMantissa isn't 0 also, or it would have been caught above so + // this is a subnormal value, pretend exponent is 1 and don't add leading bit + + ret.Add(((float)mantissas[i] / (float)leadbit[i]) * Math.Pow(2.0f, (float)1.0f - 15.0f)); + } + } + } } else { @@ -426,6 +459,7 @@ namespace renderdocui.Code var regExpr = @"^(row_major\s+)?" + // row_major matrix @"(" + @"uintten|unormten" + + @"|floateleven" + @"|unormh|unormb" + @"|snormh|snormb" + @"|bool" + // bool is stored as 4-byte int @@ -608,6 +642,12 @@ namespace renderdocui.Code fmt.special = true; fmt.specialFormat = SpecialFormat.R10G10B10A2; } + else if (basetype == "floateleven") + { + fmt = new ResourceFormat(FormatComponentType.Float, 3 * count, 1); + fmt.special = true; + fmt.specialFormat = SpecialFormat.R11G11B10; + } else { errors = "Unrecognised basic type on line:\n" + line; diff --git a/renderdocui/Controls/BufferFormatSpecifier.resx b/renderdocui/Controls/BufferFormatSpecifier.resx index 4d227ab13..5062db335 100644 --- a/renderdocui/Controls/BufferFormatSpecifier.resx +++ b/renderdocui/Controls/BufferFormatSpecifier.resx @@ -125,7 +125,7 @@ Basic types accepted: bool, byte, short, int, half, float, double. Unsigned integer types: ubyte, ushort, uint Hex-formatted integer types: xbyte, xshort, xint -Additionally special formats: unorm[hb] (half, byte) and snorm[hb], and uintten/unormten (10:10:10:2 packing) +Additionally special formats: unorm[hb] (half, byte) and snorm[hb], uintten/unormten (10:10:10:2 packing), floateleven (11:11:10F packing) Vectors (e.g. float4), matrices ([row_major] half3x4) and arrays (float[16]) are supported. diff --git a/renderdocui/Windows/PipelineState/D3D11PipelineStateViewer.cs b/renderdocui/Windows/PipelineState/D3D11PipelineStateViewer.cs index d41b52c71..71c472afc 100644 --- a/renderdocui/Windows/PipelineState/D3D11PipelineStateViewer.cs +++ b/renderdocui/Windows/PipelineState/D3D11PipelineStateViewer.cs @@ -2042,10 +2042,17 @@ namespace renderdocui.Windows.PipelineState { if (view != null) { - if (view.Format.special && view.Format.specialFormat == SpecialFormat.R10G10B10A2) + if (view.Format.special) { - if (view.Format.compType == FormatComponentType.UInt) format = "uintten"; - if (view.Format.compType == FormatComponentType.UNorm) format = "unormten"; + if (view.Format.specialFormat == SpecialFormat.R10G10B10A2) + { + if (view.Format.compType == FormatComponentType.UInt) format = "uintten"; + if (view.Format.compType == FormatComponentType.UNorm) format = "unormten"; + } + else if (view.Format.specialFormat == SpecialFormat.R11G11B10) + { + format = "floateleven"; + } } else if (!view.Format.special) { diff --git a/renderdocui/Windows/PipelineState/D3D12PipelineStateViewer.cs b/renderdocui/Windows/PipelineState/D3D12PipelineStateViewer.cs index 9b10b2209..41a0bf20a 100644 --- a/renderdocui/Windows/PipelineState/D3D12PipelineStateViewer.cs +++ b/renderdocui/Windows/PipelineState/D3D12PipelineStateViewer.cs @@ -1721,10 +1721,17 @@ namespace renderdocui.Windows.PipelineState { if (view != null) { - if (view.Format.special && view.Format.specialFormat == SpecialFormat.R10G10B10A2) + if (view.Format.special) { - if (view.Format.compType == FormatComponentType.UInt) format = "uintten"; - if (view.Format.compType == FormatComponentType.UNorm) format = "unormten"; + if (view.Format.specialFormat == SpecialFormat.R10G10B10A2) + { + if (view.Format.compType == FormatComponentType.UInt) format = "uintten"; + if (view.Format.compType == FormatComponentType.UNorm) format = "unormten"; + } + else if (view.Format.specialFormat == SpecialFormat.R11G11B10) + { + format = "floateleven"; + } } else if (!view.Format.special) {