mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-25 20:50:15 +00:00
Implement EMIT and SETEMIT
This commit is contained in:
parent
bb6f0d6010
commit
f02650b0d8
@ -63,6 +63,15 @@ struct State {
|
|||||||
|
|
||||||
// This is constructed with a dummy triangle topology
|
// This is constructed with a dummy triangle topology
|
||||||
PrimitiveAssembler<Shader::OutputVertex> primitive_assembler;
|
PrimitiveAssembler<Shader::OutputVertex> primitive_assembler;
|
||||||
|
|
||||||
|
/// Current geometry shader state
|
||||||
|
struct GeometryShaderState {
|
||||||
|
// Buffer used for geometry shader inputs
|
||||||
|
Shader::InputVertex buffer;
|
||||||
|
// The current index into the buffer
|
||||||
|
unsigned int index;
|
||||||
|
} gs_input_buffer;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern State g_state; ///< Current Pica state
|
extern State g_state; ///< Current Pica state
|
||||||
|
@ -316,6 +316,33 @@ void WriteSwizzlePatterns(bool gs, u32 value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<bool Debug>
|
||||||
|
void HandleEMIT(UnitState<Debug>& state) {
|
||||||
|
auto &config = g_state.regs.gs;
|
||||||
|
auto &emit_params = state.emit_params;
|
||||||
|
auto &emit_buffers = state.emit_buffers;
|
||||||
|
|
||||||
|
ASSERT(emit_params.vertex_id < 3);
|
||||||
|
|
||||||
|
emit_buffers[emit_params.vertex_id] = state.output_registers;
|
||||||
|
|
||||||
|
if (emit_params.primitive_emit) {
|
||||||
|
ASSERT_MSG(state.emit_triangle_callback, "EMIT invoked but no handler set!");
|
||||||
|
OutputVertex v0 = emit_buffers[0].ToVertex(config);
|
||||||
|
OutputVertex v1 = emit_buffers[1].ToVertex(config);
|
||||||
|
OutputVertex v2 = emit_buffers[2].ToVertex(config);
|
||||||
|
if (emit_params.winding) {
|
||||||
|
state.emit_triangle_callback(v2, v1, v0);
|
||||||
|
} else {
|
||||||
|
state.emit_triangle_callback(v0, v1, v2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Explicit instantiation
|
||||||
|
template void HandleEMIT(UnitState<false>& state);
|
||||||
|
template void HandleEMIT(UnitState<true>& state);
|
||||||
|
|
||||||
} // namespace Shader
|
} // namespace Shader
|
||||||
|
|
||||||
} // namespace Pica
|
} // namespace Pica
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "video_core/pica.h"
|
#include "video_core/pica.h"
|
||||||
#include "video_core/pica_types.h"
|
#include "video_core/pica_types.h"
|
||||||
|
#include "video_core/primitive_assembly.h"
|
||||||
|
|
||||||
using nihstro::RegisterType;
|
using nihstro::RegisterType;
|
||||||
using nihstro::SourceRegister;
|
using nihstro::SourceRegister;
|
||||||
@ -285,6 +286,17 @@ struct UnitState {
|
|||||||
} registers;
|
} registers;
|
||||||
static_assert(std::is_pod<Registers>::value, "Structure is not POD");
|
static_assert(std::is_pod<Registers>::value, "Structure is not POD");
|
||||||
|
|
||||||
|
OutputRegisters emit_buffers[3]; //TODO: 3dbrew suggests this only stores the first 7 output registers
|
||||||
|
|
||||||
|
union EmitParameters {
|
||||||
|
u32 raw;
|
||||||
|
BitField<22, 1, u32> winding;
|
||||||
|
BitField<23, 1, u32> primitive_emit;
|
||||||
|
BitField<24, 2, u32> vertex_id;
|
||||||
|
} emit_params;
|
||||||
|
|
||||||
|
PrimitiveAssembler<OutputVertex>::TriangleHandler emit_triangle_callback;
|
||||||
|
|
||||||
OutputRegisters output_registers;
|
OutputRegisters output_registers;
|
||||||
|
|
||||||
bool conditional_code[2];
|
bool conditional_code[2];
|
||||||
@ -322,6 +334,10 @@ struct UnitState {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t EmitParamsOffset() {
|
||||||
|
return offsetof(UnitState, emit_params.raw);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Clears the shader cache
|
/// Clears the shader cache
|
||||||
@ -401,6 +417,9 @@ void WriteProgramCode(bool gs, u32 value);
|
|||||||
void WriteSwizzlePatternsOffset(bool gs, u32 value);
|
void WriteSwizzlePatternsOffset(bool gs, u32 value);
|
||||||
void WriteSwizzlePatterns(bool gs, u32 value);
|
void WriteSwizzlePatterns(bool gs, u32 value);
|
||||||
|
|
||||||
|
template<bool Debug>
|
||||||
|
void HandleEMIT(UnitState<Debug>& state);
|
||||||
|
|
||||||
} // namespace Shader
|
} // namespace Shader
|
||||||
|
|
||||||
} // namespace Pica
|
} // namespace Pica
|
||||||
|
@ -631,6 +631,16 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case OpCode::Id::EMIT: {
|
||||||
|
Shader::HandleEMIT(state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case OpCode::Id::SETEMIT: {
|
||||||
|
state.emit_params.raw = program_code[program_counter];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_ERROR(HW_GPU, "Unhandled instruction: 0x%02x (%s): 0x%08x",
|
LOG_ERROR(HW_GPU, "Unhandled instruction: 0x%02x (%s): 0x%08x",
|
||||||
(int)instr.opcode.Value().EffectiveOpCode(), instr.opcode.Value().GetInfo().name, instr.hex);
|
(int)instr.opcode.Value().EffectiveOpCode(), instr.opcode.Value().GetInfo().name, instr.hex);
|
||||||
|
@ -73,8 +73,8 @@ const JitFunction instr_table[64] = {
|
|||||||
&JitShader::Compile_IF, // ifu
|
&JitShader::Compile_IF, // ifu
|
||||||
&JitShader::Compile_IF, // ifc
|
&JitShader::Compile_IF, // ifc
|
||||||
&JitShader::Compile_LOOP, // loop
|
&JitShader::Compile_LOOP, // loop
|
||||||
nullptr, // emit
|
&JitShader::Compile_EMIT, // emit
|
||||||
nullptr, // sete
|
&JitShader::Compile_SETEMIT, // setemit
|
||||||
&JitShader::Compile_JMP, // jmpc
|
&JitShader::Compile_JMP, // jmpc
|
||||||
&JitShader::Compile_JMP, // jmpu
|
&JitShader::Compile_JMP, // jmpu
|
||||||
&JitShader::Compile_CMP, // cmp
|
&JitShader::Compile_CMP, // cmp
|
||||||
@ -727,6 +727,22 @@ void JitShader::Compile_LOOP(Instruction instr) {
|
|||||||
looping = false;
|
looping = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void Handle_EMIT(void* param1) {
|
||||||
|
UnitState<false>& state = *static_cast<UnitState<false>*>(param1);
|
||||||
|
Shader::HandleEMIT(state);
|
||||||
|
};
|
||||||
|
|
||||||
|
void JitShader::Compile_EMIT(Instruction instr) {
|
||||||
|
ABI_PushRegistersAndAdjustStack(PersistentCallerSavedRegs(), 0);
|
||||||
|
MOV(PTRBITS, R(ABI_PARAM1), R(STATE));
|
||||||
|
ABI_CallFunctionR(reinterpret_cast<const void*>(Handle_EMIT), ABI_PARAM1);
|
||||||
|
ABI_PopRegistersAndAdjustStack(PersistentCallerSavedRegs(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitShader::Compile_SETEMIT(Instruction instr) {
|
||||||
|
MOV(32, MDisp(STATE, UnitState<false>::EmitParamsOffset()), Imm32(*(u32*)&instr.setemit));
|
||||||
|
}
|
||||||
|
|
||||||
void JitShader::Compile_JMP(Instruction instr) {
|
void JitShader::Compile_JMP(Instruction instr) {
|
||||||
if (instr.opcode.Value() == OpCode::Id::JMPC)
|
if (instr.opcode.Value() == OpCode::Id::JMPC)
|
||||||
Compile_EvaluateCondition(instr);
|
Compile_EvaluateCondition(instr);
|
||||||
|
@ -65,6 +65,8 @@ public:
|
|||||||
void Compile_CALLU(Instruction instr);
|
void Compile_CALLU(Instruction instr);
|
||||||
void Compile_IF(Instruction instr);
|
void Compile_IF(Instruction instr);
|
||||||
void Compile_LOOP(Instruction instr);
|
void Compile_LOOP(Instruction instr);
|
||||||
|
void Compile_EMIT(Instruction instr);
|
||||||
|
void Compile_SETEMIT(Instruction instr);
|
||||||
void Compile_JMP(Instruction instr);
|
void Compile_JMP(Instruction instr);
|
||||||
void Compile_CMP(Instruction instr);
|
void Compile_CMP(Instruction instr);
|
||||||
void Compile_MAD(Instruction instr);
|
void Compile_MAD(Instruction instr);
|
||||||
|
Loading…
Reference in New Issue
Block a user