Implement bitfield ops in HLSL.
This commit is contained in:
parent
7b73d135f7
commit
48f3fa4adb
113
reference/opt/shaders-hlsl/comp/bitfield.noopt.comp
Normal file
113
reference/opt/shaders-hlsl/comp/bitfield.noopt.comp
Normal file
@ -0,0 +1,113 @@
|
||||
uint SPIRV_Cross_bitfieldInsert(uint Base, uint Insert, uint Offset, uint Count)
|
||||
{
|
||||
uint Mask = Count == 32 ? 0xffffffff : (((1u << Count) - 1) << (Offset & 31));
|
||||
return (Base & ~Mask) | ((Insert << Offset) & Mask);
|
||||
}
|
||||
|
||||
uint2 SPIRV_Cross_bitfieldInsert(uint2 Base, uint2 Insert, uint Offset, uint Count)
|
||||
{
|
||||
uint Mask = Count == 32 ? 0xffffffff : (((1u << Count) - 1) << (Offset & 31));
|
||||
return (Base & ~Mask) | ((Insert << Offset) & Mask);
|
||||
}
|
||||
|
||||
uint3 SPIRV_Cross_bitfieldInsert(uint3 Base, uint3 Insert, uint Offset, uint Count)
|
||||
{
|
||||
uint Mask = Count == 32 ? 0xffffffff : (((1u << Count) - 1) << (Offset & 31));
|
||||
return (Base & ~Mask) | ((Insert << Offset) & Mask);
|
||||
}
|
||||
|
||||
uint4 SPIRV_Cross_bitfieldInsert(uint4 Base, uint4 Insert, uint Offset, uint Count)
|
||||
{
|
||||
uint Mask = Count == 32 ? 0xffffffff : (((1u << Count) - 1) << (Offset & 31));
|
||||
return (Base & ~Mask) | ((Insert << Offset) & Mask);
|
||||
}
|
||||
|
||||
uint SPIRV_Cross_bitfieldUExtract(uint Base, uint Offset, uint Count)
|
||||
{
|
||||
uint Mask = Count == 32 ? 0xffffffff : ((1 << Count) - 1);
|
||||
return (Base >> Offset) & Mask;
|
||||
}
|
||||
|
||||
uint2 SPIRV_Cross_bitfieldUExtract(uint2 Base, uint Offset, uint Count)
|
||||
{
|
||||
uint Mask = Count == 32 ? 0xffffffff : ((1 << Count) - 1);
|
||||
return (Base >> Offset) & Mask;
|
||||
}
|
||||
|
||||
uint3 SPIRV_Cross_bitfieldUExtract(uint3 Base, uint Offset, uint Count)
|
||||
{
|
||||
uint Mask = Count == 32 ? 0xffffffff : ((1 << Count) - 1);
|
||||
return (Base >> Offset) & Mask;
|
||||
}
|
||||
|
||||
uint4 SPIRV_Cross_bitfieldUExtract(uint4 Base, uint Offset, uint Count)
|
||||
{
|
||||
uint Mask = Count == 32 ? 0xffffffff : ((1 << Count) - 1);
|
||||
return (Base >> Offset) & Mask;
|
||||
}
|
||||
|
||||
int SPIRV_Cross_bitfieldSExtract(int Base, int Offset, int Count)
|
||||
{
|
||||
int Mask = Count == 32 ? -1 : ((1 << Count) - 1);
|
||||
int Masked = (Base >> Offset) & Mask;
|
||||
int ExtendShift = (32 - Count) & 31;
|
||||
return (Masked << ExtendShift) >> ExtendShift;
|
||||
}
|
||||
|
||||
int2 SPIRV_Cross_bitfieldSExtract(int2 Base, int Offset, int Count)
|
||||
{
|
||||
int Mask = Count == 32 ? -1 : ((1 << Count) - 1);
|
||||
int2 Masked = (Base >> Offset) & Mask;
|
||||
int ExtendShift = (32 - Count) & 31;
|
||||
return (Masked << ExtendShift) >> ExtendShift;
|
||||
}
|
||||
|
||||
int3 SPIRV_Cross_bitfieldSExtract(int3 Base, int Offset, int Count)
|
||||
{
|
||||
int Mask = Count == 32 ? -1 : ((1 << Count) - 1);
|
||||
int3 Masked = (Base >> Offset) & Mask;
|
||||
int ExtendShift = (32 - Count) & 31;
|
||||
return (Masked << ExtendShift) >> ExtendShift;
|
||||
}
|
||||
|
||||
int4 SPIRV_Cross_bitfieldSExtract(int4 Base, int Offset, int Count)
|
||||
{
|
||||
int Mask = Count == 32 ? -1 : ((1 << Count) - 1);
|
||||
int4 Masked = (Base >> Offset) & Mask;
|
||||
int ExtendShift = (32 - Count) & 31;
|
||||
return (Masked << ExtendShift) >> ExtendShift;
|
||||
}
|
||||
|
||||
void comp_main()
|
||||
{
|
||||
int signed_value = 0;
|
||||
uint unsigned_value = 0u;
|
||||
int3 signed_values = int3(0, 0, 0);
|
||||
uint3 unsigned_values = uint3(0u, 0u, 0u);
|
||||
int s = SPIRV_Cross_bitfieldSExtract(signed_value, 5, 20);
|
||||
uint u = SPIRV_Cross_bitfieldUExtract(unsigned_value, 6, 21);
|
||||
s = int(SPIRV_Cross_bitfieldInsert(s, 40, 5, 4));
|
||||
u = SPIRV_Cross_bitfieldInsert(u, 60u, 5, 4);
|
||||
u = reversebits(u);
|
||||
s = reversebits(s);
|
||||
int v0 = countbits(u);
|
||||
int v1 = countbits(s);
|
||||
int v2 = firstbithigh(u);
|
||||
int v3 = firstbitlow(s);
|
||||
int3 s_1 = SPIRV_Cross_bitfieldSExtract(signed_values, 5, 20);
|
||||
uint3 u_1 = SPIRV_Cross_bitfieldUExtract(unsigned_values, 6, 21);
|
||||
s_1 = int3(SPIRV_Cross_bitfieldInsert(s_1, int3(40, 40, 40), 5, 4));
|
||||
u_1 = SPIRV_Cross_bitfieldInsert(u_1, uint3(60u, 60u, 60u), 5, 4);
|
||||
u_1 = reversebits(u_1);
|
||||
s_1 = reversebits(s_1);
|
||||
int3 v0_1 = countbits(u_1);
|
||||
int3 v1_1 = countbits(s_1);
|
||||
int3 v2_1 = firstbithigh(u_1);
|
||||
int3 v3_1 = firstbitlow(s_1);
|
||||
}
|
||||
|
||||
[numthreads(1, 1, 1)]
|
||||
void main()
|
||||
{
|
||||
comp_main();
|
||||
}
|
113
reference/shaders-hlsl/comp/bitfield.noopt.comp
Normal file
113
reference/shaders-hlsl/comp/bitfield.noopt.comp
Normal file
@ -0,0 +1,113 @@
|
||||
uint SPIRV_Cross_bitfieldInsert(uint Base, uint Insert, uint Offset, uint Count)
|
||||
{
|
||||
uint Mask = Count == 32 ? 0xffffffff : (((1u << Count) - 1) << (Offset & 31));
|
||||
return (Base & ~Mask) | ((Insert << Offset) & Mask);
|
||||
}
|
||||
|
||||
uint2 SPIRV_Cross_bitfieldInsert(uint2 Base, uint2 Insert, uint Offset, uint Count)
|
||||
{
|
||||
uint Mask = Count == 32 ? 0xffffffff : (((1u << Count) - 1) << (Offset & 31));
|
||||
return (Base & ~Mask) | ((Insert << Offset) & Mask);
|
||||
}
|
||||
|
||||
uint3 SPIRV_Cross_bitfieldInsert(uint3 Base, uint3 Insert, uint Offset, uint Count)
|
||||
{
|
||||
uint Mask = Count == 32 ? 0xffffffff : (((1u << Count) - 1) << (Offset & 31));
|
||||
return (Base & ~Mask) | ((Insert << Offset) & Mask);
|
||||
}
|
||||
|
||||
uint4 SPIRV_Cross_bitfieldInsert(uint4 Base, uint4 Insert, uint Offset, uint Count)
|
||||
{
|
||||
uint Mask = Count == 32 ? 0xffffffff : (((1u << Count) - 1) << (Offset & 31));
|
||||
return (Base & ~Mask) | ((Insert << Offset) & Mask);
|
||||
}
|
||||
|
||||
uint SPIRV_Cross_bitfieldUExtract(uint Base, uint Offset, uint Count)
|
||||
{
|
||||
uint Mask = Count == 32 ? 0xffffffff : ((1 << Count) - 1);
|
||||
return (Base >> Offset) & Mask;
|
||||
}
|
||||
|
||||
uint2 SPIRV_Cross_bitfieldUExtract(uint2 Base, uint Offset, uint Count)
|
||||
{
|
||||
uint Mask = Count == 32 ? 0xffffffff : ((1 << Count) - 1);
|
||||
return (Base >> Offset) & Mask;
|
||||
}
|
||||
|
||||
uint3 SPIRV_Cross_bitfieldUExtract(uint3 Base, uint Offset, uint Count)
|
||||
{
|
||||
uint Mask = Count == 32 ? 0xffffffff : ((1 << Count) - 1);
|
||||
return (Base >> Offset) & Mask;
|
||||
}
|
||||
|
||||
uint4 SPIRV_Cross_bitfieldUExtract(uint4 Base, uint Offset, uint Count)
|
||||
{
|
||||
uint Mask = Count == 32 ? 0xffffffff : ((1 << Count) - 1);
|
||||
return (Base >> Offset) & Mask;
|
||||
}
|
||||
|
||||
int SPIRV_Cross_bitfieldSExtract(int Base, int Offset, int Count)
|
||||
{
|
||||
int Mask = Count == 32 ? -1 : ((1 << Count) - 1);
|
||||
int Masked = (Base >> Offset) & Mask;
|
||||
int ExtendShift = (32 - Count) & 31;
|
||||
return (Masked << ExtendShift) >> ExtendShift;
|
||||
}
|
||||
|
||||
int2 SPIRV_Cross_bitfieldSExtract(int2 Base, int Offset, int Count)
|
||||
{
|
||||
int Mask = Count == 32 ? -1 : ((1 << Count) - 1);
|
||||
int2 Masked = (Base >> Offset) & Mask;
|
||||
int ExtendShift = (32 - Count) & 31;
|
||||
return (Masked << ExtendShift) >> ExtendShift;
|
||||
}
|
||||
|
||||
int3 SPIRV_Cross_bitfieldSExtract(int3 Base, int Offset, int Count)
|
||||
{
|
||||
int Mask = Count == 32 ? -1 : ((1 << Count) - 1);
|
||||
int3 Masked = (Base >> Offset) & Mask;
|
||||
int ExtendShift = (32 - Count) & 31;
|
||||
return (Masked << ExtendShift) >> ExtendShift;
|
||||
}
|
||||
|
||||
int4 SPIRV_Cross_bitfieldSExtract(int4 Base, int Offset, int Count)
|
||||
{
|
||||
int Mask = Count == 32 ? -1 : ((1 << Count) - 1);
|
||||
int4 Masked = (Base >> Offset) & Mask;
|
||||
int ExtendShift = (32 - Count) & 31;
|
||||
return (Masked << ExtendShift) >> ExtendShift;
|
||||
}
|
||||
|
||||
void comp_main()
|
||||
{
|
||||
int signed_value = 0;
|
||||
uint unsigned_value = 0u;
|
||||
int3 signed_values = int3(0, 0, 0);
|
||||
uint3 unsigned_values = uint3(0u, 0u, 0u);
|
||||
int s = SPIRV_Cross_bitfieldSExtract(signed_value, 5, 20);
|
||||
uint u = SPIRV_Cross_bitfieldUExtract(unsigned_value, 6, 21);
|
||||
s = int(SPIRV_Cross_bitfieldInsert(s, 40, 5, 4));
|
||||
u = SPIRV_Cross_bitfieldInsert(u, 60u, 5, 4);
|
||||
u = reversebits(u);
|
||||
s = reversebits(s);
|
||||
int v0 = countbits(u);
|
||||
int v1 = countbits(s);
|
||||
int v2 = firstbithigh(u);
|
||||
int v3 = firstbitlow(s);
|
||||
int3 s_1 = SPIRV_Cross_bitfieldSExtract(signed_values, 5, 20);
|
||||
uint3 u_1 = SPIRV_Cross_bitfieldUExtract(unsigned_values, 6, 21);
|
||||
s_1 = int3(SPIRV_Cross_bitfieldInsert(s_1, int3(40, 40, 40), 5, 4));
|
||||
u_1 = SPIRV_Cross_bitfieldInsert(u_1, uint3(60u, 60u, 60u), 5, 4);
|
||||
u_1 = reversebits(u_1);
|
||||
s_1 = reversebits(s_1);
|
||||
int3 v0_1 = countbits(u_1);
|
||||
int3 v1_1 = countbits(s_1);
|
||||
int3 v2_1 = firstbithigh(u_1);
|
||||
int3 v3_1 = firstbitlow(s_1);
|
||||
}
|
||||
|
||||
[numthreads(1, 1, 1)]
|
||||
void main()
|
||||
{
|
||||
comp_main();
|
||||
}
|
44
shaders-hlsl/comp/bitfield.noopt.comp
Normal file
44
shaders-hlsl/comp/bitfield.noopt.comp
Normal file
@ -0,0 +1,44 @@
|
||||
#version 310 es
|
||||
|
||||
void main()
|
||||
{
|
||||
int signed_value = 0;
|
||||
uint unsigned_value = 0u;
|
||||
|
||||
ivec3 signed_values = ivec3(0);
|
||||
uvec3 unsigned_values = uvec3(0u);
|
||||
|
||||
{
|
||||
int s = bitfieldExtract(signed_value, 5, 20);
|
||||
uint u = bitfieldExtract(unsigned_value, 6, 21);
|
||||
|
||||
s = bitfieldInsert(s, 40, 5, 4);
|
||||
u = bitfieldInsert(u, 60u, 5, 4);
|
||||
|
||||
u = bitfieldReverse(u);
|
||||
s = bitfieldReverse(s);
|
||||
|
||||
int v0 = bitCount(u);
|
||||
int v1 = bitCount(s);
|
||||
|
||||
int v2 = findMSB(u);
|
||||
int v3 = findLSB(s);
|
||||
}
|
||||
|
||||
{
|
||||
ivec3 s = bitfieldExtract(signed_values, 5, 20);
|
||||
uvec3 u = bitfieldExtract(unsigned_values, 6, 21);
|
||||
|
||||
s = bitfieldInsert(s, ivec3(40), 5, 4);
|
||||
u = bitfieldInsert(u, uvec3(60u), 5, 4);
|
||||
|
||||
u = bitfieldReverse(u);
|
||||
s = bitfieldReverse(s);
|
||||
|
||||
ivec3 v0 = bitCount(u);
|
||||
ivec3 v1 = bitCount(s);
|
||||
|
||||
ivec3 v2 = findMSB(u);
|
||||
ivec3 v3 = findLSB(s);
|
||||
}
|
||||
}
|
@ -1271,6 +1271,48 @@ void CompilerHLSL::emit_resources()
|
||||
end_scope();
|
||||
statement("");
|
||||
}
|
||||
|
||||
if (requires_bitfield_insert)
|
||||
{
|
||||
static const char *types[] = { "uint", "uint2", "uint3", "uint4" };
|
||||
for (auto &type : types)
|
||||
{
|
||||
statement(type, " SPIRV_Cross_bitfieldInsert(", type, " Base, ", type, " Insert, uint Offset, uint Count)");
|
||||
begin_scope();
|
||||
statement("uint Mask = Count == 32 ? 0xffffffff : (((1u << Count) - 1) << (Offset & 31));");
|
||||
statement("return (Base & ~Mask) | ((Insert << Offset) & Mask);");
|
||||
end_scope();
|
||||
statement("");
|
||||
}
|
||||
}
|
||||
|
||||
if (requires_bitfield_extract)
|
||||
{
|
||||
static const char *unsigned_types[] = { "uint", "uint2", "uint3", "uint4" };
|
||||
for (auto &type : unsigned_types)
|
||||
{
|
||||
statement(type, " SPIRV_Cross_bitfieldUExtract(", type, " Base, uint Offset, uint Count)");
|
||||
begin_scope();
|
||||
statement("uint Mask = Count == 32 ? 0xffffffff : ((1 << Count) - 1);");
|
||||
statement("return (Base >> Offset) & Mask;");
|
||||
end_scope();
|
||||
statement("");
|
||||
}
|
||||
|
||||
// In this overload, we will have to do sign-extension, which we will emulate by shifting up and down.
|
||||
static const char *signed_types[] = { "int", "int2", "int3", "int4" };
|
||||
for (auto &type : signed_types)
|
||||
{
|
||||
statement(type, " SPIRV_Cross_bitfieldSExtract(", type, " Base, int Offset, int Count)");
|
||||
begin_scope();
|
||||
statement("int Mask = Count == 32 ? -1 : ((1 << Count) - 1);");
|
||||
statement(type, " Masked = (Base >> Offset) & Mask;");
|
||||
statement("int ExtendShift = (32 - Count) & 31;");
|
||||
statement("return (Masked << ExtendShift) >> ExtendShift;");
|
||||
end_scope();
|
||||
statement("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string CompilerHLSL::layout_for_member(const SPIRType &type, uint32_t index)
|
||||
@ -2391,6 +2433,14 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
|
||||
case GLSLstd450UnpackDouble2x32:
|
||||
SPIRV_CROSS_THROW("packDouble2x32/unpackDouble2x32 not supported in HLSL.");
|
||||
|
||||
case GLSLstd450FindILsb:
|
||||
emit_unary_func_op(result_type, id, args[0], "firstbitlow");
|
||||
break;
|
||||
case GLSLstd450FindSMsb:
|
||||
case GLSLstd450FindUMsb:
|
||||
emit_unary_func_op(result_type, id, args[0], "firstbithigh");
|
||||
break;
|
||||
|
||||
default:
|
||||
CompilerGLSL::emit_glsl_op(result_type, id, eop, args, count);
|
||||
break;
|
||||
@ -3297,6 +3347,53 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
|
||||
break;
|
||||
}
|
||||
|
||||
case OpBitFieldInsert:
|
||||
{
|
||||
if (!requires_bitfield_insert)
|
||||
{
|
||||
requires_bitfield_insert = true;
|
||||
force_recompile = true;
|
||||
}
|
||||
|
||||
auto expr = join("SPIRV_Cross_bitfieldInsert(",
|
||||
to_expression(ops[2]), ", ",
|
||||
to_expression(ops[3]), ", ",
|
||||
to_expression(ops[4]), ", ",
|
||||
to_expression(ops[5]), ")");
|
||||
|
||||
bool forward = should_forward(ops[2]) && should_forward(ops[3]) &&
|
||||
should_forward(ops[4]) && should_forward(ops[5]);
|
||||
|
||||
auto &restype = get<SPIRType>(ops[0]);
|
||||
expr = bitcast_expression(restype, SPIRType::UInt, expr);
|
||||
emit_op(ops[0], ops[1], expr, forward);
|
||||
break;
|
||||
}
|
||||
|
||||
case OpBitFieldSExtract:
|
||||
case OpBitFieldUExtract:
|
||||
{
|
||||
if (!requires_bitfield_extract)
|
||||
{
|
||||
requires_bitfield_extract = true;
|
||||
force_recompile = true;
|
||||
}
|
||||
|
||||
if (opcode == OpBitFieldSExtract)
|
||||
TFOP(SPIRV_Cross_bitfieldSExtract);
|
||||
else
|
||||
TFOP(SPIRV_Cross_bitfieldUExtract);
|
||||
break;
|
||||
}
|
||||
|
||||
case OpBitCount:
|
||||
UFOP(countbits);
|
||||
break;
|
||||
|
||||
case OpBitReverse:
|
||||
UFOP(reversebits);
|
||||
break;
|
||||
|
||||
default:
|
||||
CompilerGLSL::emit_instruction(instruction);
|
||||
break;
|
||||
|
@ -121,6 +121,8 @@ private:
|
||||
bool requires_snorm8_packing = false;
|
||||
bool requires_unorm16_packing = false;
|
||||
bool requires_snorm16_packing = false;
|
||||
bool requires_bitfield_insert = false;
|
||||
bool requires_bitfield_extract = false;
|
||||
uint64_t required_textureSizeVariants = 0;
|
||||
void require_texture_query_variant(const SPIRType &type);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user