mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-19 04:56:32 +00:00
Implement remaining bit twiddling operations
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include "common/formatting.h"
|
||||
#include "os/os_specific.h"
|
||||
#include "spirv_op_helpers.h"
|
||||
|
||||
static bool ContainsNaNInf(const ShaderVariable &val)
|
||||
@@ -1202,6 +1203,85 @@ void ThreadState::StepNext(ShaderDebugState *state, const rdcarray<ThreadState>
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
case Op::BitCount:
|
||||
{
|
||||
OpBitCount bitwise(it);
|
||||
|
||||
ShaderVariable var = GetSrc(bitwise.base);
|
||||
|
||||
for(uint8_t c = 0; c < var.columns; c++)
|
||||
var.value.uv[c] = Bits::CountOnes(var.value.uv[c]);
|
||||
|
||||
SetDst(bitwise.result, var);
|
||||
break;
|
||||
}
|
||||
case Op::BitReverse:
|
||||
{
|
||||
OpBitReverse bitwise(it);
|
||||
|
||||
ShaderVariable var = GetSrc(bitwise.base);
|
||||
|
||||
for(uint8_t c = 0; c < var.columns; c++)
|
||||
{
|
||||
uint32_t u = var.value.uv[c];
|
||||
var.value.uv[c] = 0;
|
||||
for(uint8_t b = 0; b < 32; b++)
|
||||
{
|
||||
uint32_t bit = u & (1u << b);
|
||||
var.value.uv[c] |= bit << (31 - b);
|
||||
}
|
||||
}
|
||||
|
||||
SetDst(bitwise.result, var);
|
||||
break;
|
||||
}
|
||||
case Op::BitFieldUExtract:
|
||||
case Op::BitFieldSExtract:
|
||||
{
|
||||
OpBitFieldUExtract bitwise(it);
|
||||
|
||||
ShaderVariable var = GetSrc(bitwise.base);
|
||||
ShaderVariable offset = GetSrc(bitwise.offset);
|
||||
ShaderVariable count = GetSrc(bitwise.count);
|
||||
|
||||
for(uint8_t c = 0; c < var.columns; c++)
|
||||
{
|
||||
const uint32_t mask = (1u << count.value.uv[c]) - 1;
|
||||
|
||||
var.value.uv[c] >>= offset.value.uv[c];
|
||||
var.value.uv[c] &= (1u << count.value.uv[c]) - 1;
|
||||
|
||||
if(opdata.op == Op::BitFieldSExtract)
|
||||
{
|
||||
uint32_t topbit = (mask + 1u) >> 1u;
|
||||
if(var.value.uv[c] & topbit)
|
||||
var.value.uv[c] |= (0xffffffffu ^ mask);
|
||||
}
|
||||
}
|
||||
|
||||
SetDst(bitwise.result, var);
|
||||
break;
|
||||
}
|
||||
case Op::BitFieldInsert:
|
||||
{
|
||||
OpBitFieldInsert bitwise(it);
|
||||
|
||||
ShaderVariable var = GetSrc(bitwise.base);
|
||||
ShaderVariable insert = GetSrc(bitwise.insert);
|
||||
ShaderVariable offset = GetSrc(bitwise.offset);
|
||||
ShaderVariable count = GetSrc(bitwise.count);
|
||||
|
||||
for(uint8_t c = 0; c < var.columns; c++)
|
||||
{
|
||||
const uint32_t mask = (1u << count.value.uv[c]) - 1;
|
||||
|
||||
var.value.uv[c] &= ~(mask << offset.value.uv[c]);
|
||||
var.value.uv[c] |= (insert.value.uv[c] & mask) << offset.value.uv[c];
|
||||
}
|
||||
|
||||
SetDst(bitwise.result, var);
|
||||
break;
|
||||
}
|
||||
case Op::BitwiseOr:
|
||||
case Op::BitwiseAnd:
|
||||
case Op::BitwiseXor:
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "spirv_debug.h"
|
||||
#include <math.h>
|
||||
#include "maths/matrix.h"
|
||||
#include "os/os_specific.h"
|
||||
|
||||
namespace rdcspv
|
||||
{
|
||||
@@ -585,6 +586,51 @@ ShaderVariable Reflect(ThreadState &state, uint32_t, const rdcarray<Id> ¶ms)
|
||||
return N;
|
||||
}
|
||||
|
||||
ShaderVariable FindILsb(ThreadState &state, uint32_t, const rdcarray<Id> ¶ms)
|
||||
{
|
||||
CHECK_PARAMS(1);
|
||||
|
||||
ShaderVariable x = state.GetSrc(params[0]);
|
||||
|
||||
for(uint8_t c = 0; c < x.columns; c++)
|
||||
x.value.iv[c] = x.value.uv[c] == 0 ? -1 : Bits::CountTrailingZeroes(x.value.uv[c]);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
ShaderVariable FindSMsb(ThreadState &state, uint32_t, const rdcarray<Id> ¶ms)
|
||||
{
|
||||
CHECK_PARAMS(1);
|
||||
|
||||
ShaderVariable x = state.GetSrc(params[0]);
|
||||
|
||||
for(uint8_t c = 0; c < x.columns; c++)
|
||||
{
|
||||
if(x.value.iv[c] == 0 || x.value.iv[c] == -1)
|
||||
x.value.iv[c] = -1;
|
||||
else if(x.value.iv[c] >= 0)
|
||||
x.value.uv[c] = 31 - Bits::CountLeadingZeroes(x.value.uv[c]);
|
||||
else
|
||||
x.value.uv[c] = 31 - Bits::CountLeadingZeroes(~x.value.uv[c]);
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
ShaderVariable FindUMsb(ThreadState &state, uint32_t, const rdcarray<Id> ¶ms)
|
||||
{
|
||||
CHECK_PARAMS(1);
|
||||
|
||||
ShaderVariable x = state.GetSrc(params[0]);
|
||||
|
||||
for(uint8_t c = 0; c < x.columns; c++)
|
||||
{
|
||||
x.value.iv[c] = x.value.iv[c] == 0 ? -1 : 31 - Bits::CountLeadingZeroes(x.value.uv[c]);
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
static float GLSLNMax(float x, float y)
|
||||
{
|
||||
const bool xnan = isnan(x);
|
||||
@@ -711,6 +757,9 @@ void ConfigureGLSLStd450(ExtInstDispatcher &extinst)
|
||||
EXT(Cross);
|
||||
EXT(FaceForward);
|
||||
EXT(Reflect);
|
||||
EXT(FindILsb);
|
||||
EXT(FindSMsb);
|
||||
EXT(FindUMsb);
|
||||
EXT(NMin);
|
||||
EXT(NMax);
|
||||
EXT(NClamp);
|
||||
|
||||
@@ -258,6 +258,8 @@ TEST_CASE("Test OS-specific functions", "[osspecific]")
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 32);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 32);
|
||||
CHECK(Bits::CountOnes(val) == 0);
|
||||
}
|
||||
|
||||
val = 1;
|
||||
@@ -265,6 +267,8 @@ TEST_CASE("Test OS-specific functions", "[osspecific]")
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 31);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 0);
|
||||
CHECK(Bits::CountOnes(val) == 1);
|
||||
}
|
||||
|
||||
val <<= 1;
|
||||
@@ -272,6 +276,8 @@ TEST_CASE("Test OS-specific functions", "[osspecific]")
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 30);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 1);
|
||||
CHECK(Bits::CountOnes(val) == 1);
|
||||
}
|
||||
|
||||
val <<= 4;
|
||||
@@ -279,6 +285,8 @@ TEST_CASE("Test OS-specific functions", "[osspecific]")
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 26);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 5);
|
||||
CHECK(Bits::CountOnes(val) == 1);
|
||||
}
|
||||
|
||||
val++;
|
||||
@@ -286,6 +294,8 @@ TEST_CASE("Test OS-specific functions", "[osspecific]")
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 26);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 0);
|
||||
CHECK(Bits::CountOnes(val) == 2);
|
||||
}
|
||||
|
||||
val += 5;
|
||||
@@ -293,6 +303,8 @@ TEST_CASE("Test OS-specific functions", "[osspecific]")
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 26);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 1);
|
||||
CHECK(Bits::CountOnes(val) == 3);
|
||||
}
|
||||
|
||||
val += 1000;
|
||||
@@ -300,6 +312,8 @@ TEST_CASE("Test OS-specific functions", "[osspecific]")
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 21);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 1);
|
||||
CHECK(Bits::CountOnes(val) == 4);
|
||||
}
|
||||
|
||||
val *= 3;
|
||||
@@ -307,6 +321,8 @@ TEST_CASE("Test OS-specific functions", "[osspecific]")
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 20);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 1);
|
||||
CHECK(Bits::CountOnes(val) == 5);
|
||||
}
|
||||
|
||||
val *= 200000;
|
||||
@@ -314,6 +330,17 @@ TEST_CASE("Test OS-specific functions", "[osspecific]")
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 2);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 7);
|
||||
CHECK(Bits::CountOnes(val) == 12);
|
||||
}
|
||||
|
||||
val |= 0xFFFFFFFFu;
|
||||
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 0);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 0);
|
||||
CHECK(Bits::CountOnes(val) == 32);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -325,6 +352,8 @@ TEST_CASE("Test OS-specific functions", "[osspecific]")
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 64);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 64);
|
||||
CHECK(Bits::CountOnes(val) == 0);
|
||||
}
|
||||
|
||||
val = 1;
|
||||
@@ -332,6 +361,8 @@ TEST_CASE("Test OS-specific functions", "[osspecific]")
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 63);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 0);
|
||||
CHECK(Bits::CountOnes(val) == 1);
|
||||
}
|
||||
|
||||
val <<= 1;
|
||||
@@ -339,6 +370,8 @@ TEST_CASE("Test OS-specific functions", "[osspecific]")
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 62);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 1);
|
||||
CHECK(Bits::CountOnes(val) == 1);
|
||||
}
|
||||
|
||||
val <<= 4;
|
||||
@@ -346,6 +379,8 @@ TEST_CASE("Test OS-specific functions", "[osspecific]")
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 58);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 5);
|
||||
CHECK(Bits::CountOnes(val) == 1);
|
||||
}
|
||||
|
||||
val++;
|
||||
@@ -353,6 +388,8 @@ TEST_CASE("Test OS-specific functions", "[osspecific]")
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 58);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 0);
|
||||
CHECK(Bits::CountOnes(val) == 2);
|
||||
}
|
||||
|
||||
val += 5;
|
||||
@@ -360,6 +397,8 @@ TEST_CASE("Test OS-specific functions", "[osspecific]")
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 58);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 1);
|
||||
CHECK(Bits::CountOnes(val) == 3);
|
||||
}
|
||||
|
||||
val += 1000;
|
||||
@@ -367,6 +406,8 @@ TEST_CASE("Test OS-specific functions", "[osspecific]")
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 53);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 1);
|
||||
CHECK(Bits::CountOnes(val) == 4);
|
||||
}
|
||||
|
||||
val *= 3;
|
||||
@@ -374,6 +415,8 @@ TEST_CASE("Test OS-specific functions", "[osspecific]")
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 52);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 1);
|
||||
CHECK(Bits::CountOnes(val) == 5);
|
||||
}
|
||||
|
||||
val *= 200000;
|
||||
@@ -381,6 +424,8 @@ TEST_CASE("Test OS-specific functions", "[osspecific]")
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 34);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 7);
|
||||
CHECK(Bits::CountOnes(val) == 12);
|
||||
}
|
||||
|
||||
val *= 1000000;
|
||||
@@ -388,6 +433,17 @@ TEST_CASE("Test OS-specific functions", "[osspecific]")
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 14);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 13);
|
||||
CHECK(Bits::CountOnes(val) == 19);
|
||||
}
|
||||
|
||||
val |= 0xFFFFFFFFFFFFFFFFull;
|
||||
|
||||
{
|
||||
INFO("val is " << val);
|
||||
CHECK(Bits::CountLeadingZeroes(val) == 0);
|
||||
CHECK(Bits::CountTrailingZeroes(val) == 0);
|
||||
CHECK(Bits::CountOnes(val) == 64);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -120,4 +120,28 @@ inline uint64_t CountLeadingZeroes(uint64_t value)
|
||||
return value == 0 ? 64 : __builtin_clzl(value);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline uint32_t CountTrailingZeroes(uint32_t value)
|
||||
{
|
||||
return value == 0 ? 32 : __builtin_ctz(value);
|
||||
}
|
||||
|
||||
#if ENABLED(RDOC_X64)
|
||||
inline uint64_t CountTrailingZeroes(uint64_t value)
|
||||
{
|
||||
return value == 0 ? 64 : __builtin_ctzl(value);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline uint32_t CountOnes(uint32_t value)
|
||||
{
|
||||
return __builtin_popcount(value);
|
||||
}
|
||||
|
||||
#if ENABLED(RDOC_X64)
|
||||
inline uint64_t CountOnes(uint64_t value)
|
||||
{
|
||||
return __builtin_popcountl(value);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -83,4 +83,32 @@ inline uint64_t CountLeadingZeroes(uint64_t value)
|
||||
return (result == TRUE) ? (index ^ 63) : 64;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline uint32_t CountTrailingZeroes(uint32_t value)
|
||||
{
|
||||
DWORD index;
|
||||
BOOLEAN result = _BitScanForward(&index, value);
|
||||
return (result == TRUE) ? index : 32;
|
||||
}
|
||||
|
||||
#if ENABLED(RDOC_X64)
|
||||
inline uint64_t CountTrailingZeroes(uint64_t value)
|
||||
{
|
||||
DWORD index;
|
||||
BOOLEAN result = _BitScanForward64(&index, value);
|
||||
return (result == TRUE) ? index : 64;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline uint32_t CountOnes(uint32_t value)
|
||||
{
|
||||
return __popcnt(value);
|
||||
}
|
||||
|
||||
#if ENABLED(RDOC_X64)
|
||||
inline uint64_t CountOnes(uint64_t value)
|
||||
{
|
||||
return __popcnt64(value);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -847,6 +847,40 @@ void main()
|
||||
}
|
||||
)EOSHADER"
|
||||
R"EOSHADER(
|
||||
case 102:
|
||||
{
|
||||
uint a = zerou + 0x0dadbeef;
|
||||
int b = zeroi + 0x0dadbeef;
|
||||
|
||||
Color = vec4(float(findLSB(a)), float(findLSB(b)), float(findMSB(a)), float(findMSB(b)));
|
||||
break;
|
||||
}
|
||||
case 103:
|
||||
{
|
||||
int a = zeroi - 0x0dadbeef;
|
||||
|
||||
Color = vec4(float(findLSB(a)), float(findLSB(zeroi)), float(findMSB(a)), float(findMSB(zeroi)));
|
||||
break;
|
||||
}
|
||||
case 104:
|
||||
{
|
||||
uint a = zerou + 0x44b82a24;
|
||||
int b = zeroi + 0x44b82a24;
|
||||
|
||||
Color = vec4(float(bitCount(a)), float(bitCount(b)), uintBitsToFloat(bitfieldReverse(a)), intBitsToFloat(bitfieldReverse(b)));
|
||||
break;
|
||||
}
|
||||
case 105:
|
||||
{
|
||||
uint a = zerou + 0x44b82a24;
|
||||
int b = zeroi + 0x44b82a24;
|
||||
uint af = zerou+0xffffffff;
|
||||
int bf = zeroi-1;
|
||||
|
||||
Color = vec4(float(bitfieldExtract(a, 4, 5)), float(bitfieldExtract(b, 4, 5)),
|
||||
uintBitsToFloat(bitfieldInsert(a, af, 4, 5)), intBitsToFloat(bitfieldInsert(b, bf, 4, 5)));
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user