diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp index b12dc5ba8..271ce205b 100644 --- a/src/video_core/shader/decode/arithmetic_integer.cpp +++ b/src/video_core/shader/decode/arithmetic_integer.cpp @@ -119,6 +119,16 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { SetRegister(bb, instr.gpr0, value); break; } + case OpCode::Id::POPC_C: + case OpCode::Id::POPC_R: + case OpCode::Id::POPC_IMM: { + if (instr.popc.invert) { + op_b = Operation(OperationCode::IBitwiseNot, NO_PRECISE, op_b); + } + const Node value = Operation(OperationCode::IBitCount, PRECISE, op_b); + SetRegister(bb, instr.gpr0, value); + break; + } case OpCode::Id::SEL_C: case OpCode::Id::SEL_R: case OpCode::Id::SEL_IMM: { diff --git a/src/video_core/shader/glsl_decompiler.cpp b/src/video_core/shader/glsl_decompiler.cpp index b93ea9ec6..1aff62882 100644 --- a/src/video_core/shader/glsl_decompiler.cpp +++ b/src/video_core/shader/glsl_decompiler.cpp @@ -908,6 +908,11 @@ private: Type::Int); } + template + std::string BitCount(Operation operation) { + return GenerateUnary(operation, "bitCount", type, type, false); + } + std::string HNegate(Operation operation) { const auto GetNegate = [&](std::size_t index) -> std::string { if (const auto pred = std::get_if(operation[index])) { @@ -1273,6 +1278,7 @@ private: &BitwiseXor, &BitwiseNot, &BitfieldInsert, + &BitCount, &Add, &Mul, @@ -1289,6 +1295,7 @@ private: &BitwiseXor, &BitwiseNot, &BitfieldInsert, + &BitCount, &Add, &Mul, diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 1f39dc6d0..1fc838d15 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -386,6 +386,8 @@ void ShaderIR::SetLocalMemory(BasicBlock& bb, Node address, Node value) { return OperationCode::UBitwiseNot; case OperationCode::IBitfieldInsert: return OperationCode::UBitfieldInsert; + case OperationCode::IBitCount: + return OperationCode::UBitCount; case OperationCode::LogicalILessThan: return OperationCode::LogicalULessThan; case OperationCode::LogicalIEqual: diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 231f58f6a..ccdf316ac 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -89,6 +89,7 @@ enum class OperationCode { IBitwiseXor, /// (MetaArithmetic, int a, int b) -> int IBitwiseNot, /// (MetaArithmetic, int a) -> int IBitfieldInsert, /// (MetaArithmetic, int base, int insert, int offset, int bits) -> int + IBitCount, /// (MetaArithmetic, int) -> int UAdd, /// (MetaArithmetic, uint a, uint b) -> uint UMul, /// (MetaArithmetic, uint a, uint b) -> uint @@ -103,8 +104,9 @@ enum class OperationCode { UBitwiseAnd, /// (MetaArithmetic, uint a, uint b) -> uint UBitwiseOr, /// (MetaArithmetic, uint a, uint b) -> uint UBitwiseXor, /// (MetaArithmetic, uint a, uint b) -> uint - UBitwiseNot, /// (MetaArithmetic, uint a) -> int + UBitwiseNot, /// (MetaArithmetic, uint a) -> uint UBitfieldInsert, /// (MetaArithmetic, uint base, uint insert, int offset, int bits) -> uint + UBitCount, /// (MetaArithmetic, uint) -> uint HAdd, /// (MetaHalfArithmetic, f16vec2 a, f16vec2 b) -> f16vec2 HMul, /// (MetaHalfArithmetic, f16vec2 a, f16vec2 b) -> f16vec2