shader: Implement OUT
This commit is contained in:
		| @@ -134,6 +134,7 @@ add_library(shader_recompiler STATIC | ||||
|     frontend/maxwell/translate/impl/move_register_to_predicate.cpp | ||||
|     frontend/maxwell/translate/impl/move_special_register.cpp | ||||
|     frontend/maxwell/translate/impl/not_implemented.cpp | ||||
|     frontend/maxwell/translate/impl/output_geometry.cpp | ||||
|     frontend/maxwell/translate/impl/predicate_set_predicate.cpp | ||||
|     frontend/maxwell/translate/impl/predicate_set_register.cpp | ||||
|     frontend/maxwell/translate/impl/select_source_with_predicate.cpp | ||||
|   | ||||
| @@ -34,6 +34,8 @@ void EmitMemoryBarrierDeviceLevel(EmitContext& ctx); | ||||
| void EmitMemoryBarrierSystemLevel(EmitContext& ctx); | ||||
| void EmitPrologue(EmitContext& ctx); | ||||
| void EmitEpilogue(EmitContext& ctx); | ||||
| void EmitEmitVertex(EmitContext& ctx, Id stream); | ||||
| void EmitEndPrimitive(EmitContext& ctx, Id stream); | ||||
| void EmitGetRegister(EmitContext& ctx); | ||||
| void EmitSetRegister(EmitContext& ctx); | ||||
| void EmitGetPred(EmitContext& ctx); | ||||
|   | ||||
| @@ -36,4 +36,12 @@ void EmitEpilogue(EmitContext& ctx) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| void EmitEmitVertex(EmitContext& ctx, Id stream) { | ||||
|     ctx.OpEmitStreamVertex(stream); | ||||
| } | ||||
|  | ||||
| void EmitEndPrimitive(EmitContext& ctx, Id stream) { | ||||
|     ctx.OpEndStreamPrimitive(stream); | ||||
| } | ||||
|  | ||||
| } // namespace Shader::Backend::SPIRV | ||||
|   | ||||
| @@ -125,6 +125,14 @@ void IREmitter::Epilogue() { | ||||
|     Inst(Opcode::Epilogue); | ||||
| } | ||||
|  | ||||
| void IREmitter::EmitVertex(const U32& stream) { | ||||
|     Inst(Opcode::EmitVertex, stream); | ||||
| } | ||||
|  | ||||
| void IREmitter::EndPrimitive(const U32& stream) { | ||||
|     Inst(Opcode::EndPrimitive, stream); | ||||
| } | ||||
|  | ||||
| U32 IREmitter::GetReg(IR::Reg reg) { | ||||
|     return Inst<U32>(Opcode::GetRegister, reg); | ||||
| } | ||||
|   | ||||
| @@ -43,6 +43,9 @@ public: | ||||
|     void Prologue(); | ||||
|     void Epilogue(); | ||||
|  | ||||
|     void EmitVertex(const U32& stream); | ||||
|     void EndPrimitive(const U32& stream); | ||||
|  | ||||
|     [[nodiscard]] U32 GetReg(IR::Reg reg); | ||||
|     void SetReg(IR::Reg reg, const U32& value); | ||||
|  | ||||
|   | ||||
| @@ -69,6 +69,8 @@ bool Inst::MayHaveSideEffects() const noexcept { | ||||
|     case Opcode::MemoryBarrierSystemLevel: | ||||
|     case Opcode::Prologue: | ||||
|     case Opcode::Epilogue: | ||||
|     case Opcode::EmitVertex: | ||||
|     case Opcode::EndPrimitive: | ||||
|     case Opcode::SetAttribute: | ||||
|     case Opcode::SetAttributeIndexed: | ||||
|     case Opcode::SetFragColor: | ||||
|   | ||||
| @@ -25,6 +25,8 @@ OPCODE(MemoryBarrierSystemLevel,                            Void, | ||||
| // Special operations | ||||
| OPCODE(Prologue,                                            Void,                                                                                           ) | ||||
| OPCODE(Epilogue,                                            Void,                                                                                           ) | ||||
| OPCODE(EmitVertex,                                          Void,           U32,                                                                            ) | ||||
| OPCODE(EndPrimitive,                                        Void,           U32,                                                                            ) | ||||
|  | ||||
| // Context getters/setters | ||||
| OPCODE(GetRegister,                                         U32,            Reg,                                                                            ) | ||||
|   | ||||
| @@ -64,7 +64,7 @@ void TranslatorVisitor::ALD(u64 insn) { | ||||
|         BitField<8, 8, IR::Reg> index_reg; | ||||
|         BitField<20, 10, u64> absolute_offset; | ||||
|         BitField<20, 11, s64> relative_offset; | ||||
|         BitField<39, 8, IR::Reg> stream_reg; | ||||
|         BitField<39, 8, IR::Reg> array_reg; | ||||
|         BitField<32, 1, u64> o; | ||||
|         BitField<31, 1, u64> patch; | ||||
|         BitField<47, 2, Size> size; | ||||
| @@ -100,16 +100,13 @@ void TranslatorVisitor::AST(u64 insn) { | ||||
|         BitField<20, 10, u64> absolute_offset; | ||||
|         BitField<20, 11, s64> relative_offset; | ||||
|         BitField<31, 1, u64> patch; | ||||
|         BitField<39, 8, IR::Reg> stream_reg; | ||||
|         BitField<39, 8, IR::Reg> array_reg; | ||||
|         BitField<47, 2, Size> size; | ||||
|     } const ast{insn}; | ||||
|  | ||||
|     if (ast.patch != 0) { | ||||
|         throw NotImplementedException("P"); | ||||
|     } | ||||
|     if (ast.stream_reg != IR::Reg::RZ) { | ||||
|         throw NotImplementedException("Stream store"); | ||||
|     } | ||||
|     if (ast.index_reg != IR::Reg::RZ) { | ||||
|         throw NotImplementedException("Indexed store"); | ||||
|     } | ||||
|   | ||||
| @@ -169,18 +169,6 @@ void TranslatorVisitor::NOP(u64) { | ||||
|     // NOP is No-Op. | ||||
| } | ||||
|  | ||||
| void TranslatorVisitor::OUT_reg(u64) { | ||||
|     ThrowNotImplemented(Opcode::OUT_reg); | ||||
| } | ||||
|  | ||||
| void TranslatorVisitor::OUT_cbuf(u64) { | ||||
|     ThrowNotImplemented(Opcode::OUT_cbuf); | ||||
| } | ||||
|  | ||||
| void TranslatorVisitor::OUT_imm(u64) { | ||||
|     ThrowNotImplemented(Opcode::OUT_imm); | ||||
| } | ||||
|  | ||||
| void TranslatorVisitor::PBK() { | ||||
|     // PBK is a no-op | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,45 @@ | ||||
| // Copyright 2021 yuzu Emulator Project | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #include "common/bit_field.h" | ||||
| #include "common/common_types.h" | ||||
| #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||||
|  | ||||
| namespace Shader::Maxwell { | ||||
| namespace { | ||||
| void OUT(TranslatorVisitor& v, u64 insn, IR::U32 stream_index) { | ||||
|     union { | ||||
|         u64 raw; | ||||
|         BitField<0, 8, IR::Reg> dest_reg; | ||||
|         BitField<8, 8, IR::Reg> output_reg; // Not needed on host | ||||
|         BitField<39, 1, u64> emit; | ||||
|         BitField<40, 1, u64> cut; | ||||
|     } const out{insn}; | ||||
|  | ||||
|     stream_index = v.ir.BitwiseAnd(stream_index, v.ir.Imm32(0b11)); | ||||
|  | ||||
|     if (out.emit != 0) { | ||||
|         v.ir.EmitVertex(stream_index); | ||||
|     } | ||||
|     if (out.cut != 0) { | ||||
|         v.ir.EndPrimitive(stream_index); | ||||
|     } | ||||
|     // Host doesn't need the output register, but we can write to it to avoid undefined reads | ||||
|     v.X(out.dest_reg, v.ir.Imm32(0)); | ||||
| } | ||||
| } // Anonymous namespace | ||||
|  | ||||
| void TranslatorVisitor::OUT_reg(u64 insn) { | ||||
|     OUT(*this, insn, GetReg20(insn)); | ||||
| } | ||||
|  | ||||
| void TranslatorVisitor::OUT_cbuf(u64 insn) { | ||||
|     OUT(*this, insn, GetCbuf(insn)); | ||||
| } | ||||
|  | ||||
| void TranslatorVisitor::OUT_imm(u64 insn) { | ||||
|     OUT(*this, insn, GetImm20(insn)); | ||||
| } | ||||
|  | ||||
| } // namespace Shader::Maxwell | ||||
		Reference in New Issue
	
	Block a user