diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp index 473dc83642..6aa132e629 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp @@ -225,4 +225,28 @@ void EmitConvertF64U64(EmitContext& ctx, IR::Inst& inst, Register value) { Convert(ctx, inst, value, "F64", "U64", true); } +void EmitConvertU16U32(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "U32", "U16", false); +} + +void EmitConvertU32U16(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "U16", "U32", false); +} + +void EmitConvertU8U32(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "U32", "U8", false); +} + +void EmitConvertU32U8(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "U8", "U32", false); +} + +void EmitConvertS32S8(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "S8", "S32", false); +} + +void EmitConvertS32S16(EmitContext& ctx, IR::Inst& inst, Register value) { + Convert(ctx, inst, value, "S16", "S32", false); +} + } // namespace Shader::Backend::GLASM diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index c5d4835fa9..e4cc5e694b 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -541,6 +541,12 @@ void EmitConvertF64U8(EmitContext& ctx, IR::Inst& inst, Register value); void EmitConvertF64U16(EmitContext& ctx, IR::Inst& inst, Register value); void EmitConvertF64U32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value); void EmitConvertF64U64(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertU16U32(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertU32U16(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertU8U32(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertU32U8(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertS32S8(EmitContext& ctx, IR::Inst& inst, Register value); +void EmitConvertS32S16(EmitContext& ctx, IR::Inst& inst, Register value); void EmitBindlessImageSampleImplicitLod(EmitContext&); void EmitBindlessImageSampleExplicitLod(EmitContext&); void EmitBindlessImageSampleDrefImplicitLod(EmitContext&); diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_convert.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_convert.cpp index aeacb5a64c..cf404f7b51 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_convert.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_convert.cpp @@ -68,6 +68,36 @@ void EmitConvertU32F16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::I NotImplemented(); } +void EmitConvertU16U32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view value) { + NotImplemented(); +} + +void EmitConvertU32U16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view value) { + NotImplemented(); +} + +void EmitConvertU8U32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view value) { + NotImplemented(); +} + +void EmitConvertU32U8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view value) { + NotImplemented(); +} + +void EmitConvertS32S8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view value) { + NotImplemented(); +} + +void EmitConvertS32S16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, + [[maybe_unused]] std::string_view value) { + NotImplemented(); +} + void EmitConvertU32F32(EmitContext& ctx, IR::Inst& inst, std::string_view value) { ctx.AddU32("{}=uint({});", inst, value); } diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h index 9e405b37fb..fb669d399e 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h +++ b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h @@ -611,6 +611,12 @@ void EmitConvertF64U8(EmitContext& ctx, IR::Inst& inst, std::string_view value); void EmitConvertF64U16(EmitContext& ctx, IR::Inst& inst, std::string_view value); void EmitConvertF64U32(EmitContext& ctx, IR::Inst& inst, std::string_view value); void EmitConvertF64U64(EmitContext& ctx, IR::Inst& inst, std::string_view value); +void EmitConvertU16U32(EmitContext& ctx, IR::Inst& inst, std::string_view value); +void EmitConvertU32U16(EmitContext& ctx, IR::Inst& inst, std::string_view value); +void EmitConvertU8U32(EmitContext& ctx, IR::Inst& inst, std::string_view value); +void EmitConvertU32U8(EmitContext& ctx, IR::Inst& inst, std::string_view value); +void EmitConvertS32S8(EmitContext& ctx, IR::Inst& inst, std::string_view value); +void EmitConvertS32S16(EmitContext& ctx, IR::Inst& inst, std::string_view value); void EmitBindlessImageSampleImplicitLod(EmitContext&); void EmitBindlessImageSampleExplicitLod(EmitContext&); void EmitBindlessImageSampleDrefImplicitLod(EmitContext&); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_convert.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_convert.cpp index 7b6e34f315..bfe71358b1 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_convert.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_convert.cpp @@ -268,4 +268,53 @@ Id EmitConvertF64U64(EmitContext& ctx, Id value) { return ctx.OpConvertUToF(ctx.F64[1], value); } +Id EmitConvertU16U32(EmitContext& ctx, Id value) { + if (ctx.profile.support_int16) { + return ctx.OpUConvert(ctx.U16, value); + } else { + return ctx.OpBitFieldUExtract(ctx.U32[1], value, ctx.u32_zero_value, ctx.Const(16u)); + } +} + +Id EmitConvertU32U16(EmitContext& ctx, Id value) { + if (ctx.profile.support_int16) { + return ctx.OpUConvert(ctx.U32[1], value); + } else { + return ExtractU16(ctx, value); + } +} + +Id EmitConvertU8U32(EmitContext& ctx, Id value) { + if (ctx.profile.support_int8) { + return ctx.OpUConvert(ctx.U8, value); + } else { + return ExtractU8(ctx, value); + } +} + +Id EmitConvertU32U8(EmitContext& ctx, Id value) { + if (ctx.profile.support_int8) { + return ctx.OpUConvert(ctx.U32[1], value); + } else { + return ctx.OpBitFieldUExtract(ctx.U32[1], value, ctx.u32_zero_value, ctx.Const(8u)); + } +} + +// in signed +Id EmitConvertS32S8(EmitContext& ctx, Id value) { + if (ctx.profile.support_int8) { + return ctx.OpSConvert(ctx.U32[1], value); + } else { + return ctx.OpBitFieldSExtract(ctx.U32[1], value, ctx.u32_zero_value, ctx.Const(8u)); + } +} + +Id EmitConvertS32S16(EmitContext& ctx, Id value) { + if (ctx.profile.support_int16) { + return ctx.OpSConvert(ctx.U32[1], value); + } else { + return ctx.OpBitFieldSExtract(ctx.U32[1], value, ctx.u32_zero_value, ctx.Const(16u)); + } +} + } // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index b8e98e6c58..52be1369c2 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -503,6 +503,12 @@ Id EmitConvertF64U8(EmitContext& ctx, Id value); Id EmitConvertF64U16(EmitContext& ctx, Id value); Id EmitConvertF64U32(EmitContext& ctx, Id value); Id EmitConvertF64U64(EmitContext& ctx, Id value); +Id EmitConvertU16U32(EmitContext& ctx, Id value); +Id EmitConvertU32U16(EmitContext& ctx, Id value); +Id EmitConvertU8U32(EmitContext& ctx, Id value); +Id EmitConvertU32U8(EmitContext& ctx, Id value); +Id EmitConvertS32S8(EmitContext& ctx, Id value); +Id EmitConvertS32S16(EmitContext& ctx, Id value); Id EmitBindlessImageSampleImplicitLod(EmitContext&); Id EmitBindlessImageSampleExplicitLod(EmitContext&); Id EmitBindlessImageSampleDrefImplicitLod(EmitContext&); diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index e1e46cb81c..a2fa9b1588 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp @@ -1730,10 +1730,36 @@ F16F32F64 IREmitter::ConvertIToF(size_t dest_bitsize, size_t src_bitsize, bool i : ConvertUToF(dest_bitsize, src_bitsize, value, control); } -U32U64 IREmitter::UConvert(size_t result_bitsize, const U32U64& value) { +U8U16U32U64 IREmitter::UConvert(size_t result_bitsize, const U8U16U32U64& value) { switch (result_bitsize) { + case 8: + switch (value.Type()) { + case Type::U8: + // Nothing to do + return value; + case Type::U32: + return Inst(Opcode::ConvertU8U32, value); + default: + break; + } + break; + case 16: + switch (value.Type()) { + case Type::U16: + // Nothing to do + return value; + case Type::U32: + return Inst(Opcode::ConvertU16U32, value); + default: + break; + } + break; case 32: switch (value.Type()) { + case Type::U8: + return Inst(Opcode::ConvertU32U8, value); + case Type::U16: + return Inst(Opcode::ConvertU32U16, value); case Type::U32: // Nothing to do return value; @@ -1753,10 +1779,31 @@ U32U64 IREmitter::UConvert(size_t result_bitsize, const U32U64& value) { default: break; } + break; + default: + break; } throw NotImplementedException("Conversion from {} to {} bits", value.Type(), result_bitsize); } +U8U16U32U64 IR::IREmitter::SConvert(size_t result_bitsize, const U8U16U32U64& value) { + switch (result_bitsize) { + case 32: + switch (value.Type()) { + case Type::U8: + return Inst(Opcode::ConvertS32S8, value); + case Type::U16: + return Inst(Opcode::ConvertS32S16, value); + default: + break; + } + break; + default: + break; + } + throw NotImplementedException("Signed Conversion from {} to {} bits", value.Type(), result_bitsize); +} + F16F32F64 IREmitter::FPConvert(size_t result_bitsize, const F16F32F64& value, FpControl control) { switch (result_bitsize) { case 16: diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 073091ea58..48828f3ecc 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h @@ -305,7 +305,8 @@ public: [[nodiscard]] F16F32F64 ConvertIToF(size_t dest_bitsize, size_t src_bitsize, bool is_signed, const Value& value, FpControl control = {}); - [[nodiscard]] U32U64 UConvert(size_t result_bitsize, const U32U64& value); + [[nodiscard]] U8U16U32U64 UConvert(size_t result_bitsize, const U8U16U32U64& value); + [[nodiscard]] U8U16U32U64 SConvert(size_t result_bitsize, const U8U16U32U64& value); [[nodiscard]] F16F32F64 FPConvert(size_t result_bitsize, const F16F32F64& value, FpControl control = {}); diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index 2f880a8596..4a6da06f66 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc @@ -475,6 +475,12 @@ OPCODE(ConvertF64U8, F64, U32, OPCODE(ConvertF64U16, F64, U32, ) OPCODE(ConvertF64U32, F64, U32, ) OPCODE(ConvertF64U64, F64, U64, ) +OPCODE(ConvertU16U32, U16, U32, ) +OPCODE(ConvertU32U16, U32, U16, ) +OPCODE(ConvertU8U32, U8, U32, ) +OPCODE(ConvertU32U8, U32, U8, ) +OPCODE(ConvertS32S8, U32, U8, ) +OPCODE(ConvertS32S16, U32, U16, ) // Image operations OPCODE(BindlessImageSampleImplicitLod, F32x4, U32, Opaque, Opaque, Opaque, ) diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index c27546b0e1..514344dfe3 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h @@ -269,6 +269,7 @@ using F32 = TypedValue; using F64 = TypedValue; using U32U64 = TypedValue; using F32F64 = TypedValue; +using U8U16U32U64 = TypedValue; using U16U32U64 = TypedValue; using F16F32F64 = TypedValue; using UAny = TypedValue;