Skip to content

Commit

Permalink
Merge pull request #528 from wheremyfoodat/bleh
Browse files Browse the repository at this point in the history
arm64: Implement DPH/DPHI in shader recompiler, enable shader recompiler by default on Android & a64 desktop
  • Loading branch information
wheremyfoodat authored Jul 3, 2024
2 parents 35b49d0 + 31902e9 commit 1b071b6
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 4 deletions.
2 changes: 1 addition & 1 deletion include/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// Remember to initialize every field here to its default value otherwise bad things will happen
struct EmulatorConfig {
// Only enable the shader JIT by default on platforms where it's completely tested
#ifdef PANDA3DS_X64_HOST
#if defined(PANDA3DS_X64_HOST) || defined(PANDA3DS_ARM64_HOST)
static constexpr bool shaderJitDefault = true;
#else
static constexpr bool shaderJitDefault = false;
Expand Down
37 changes: 35 additions & 2 deletions src/core/PICA/dynapica/shader_rec_emitter_arm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@ void ShaderEmitter::compileInstruction(const PICAShader& shaderUnit) {
case ShaderOpcodes::CMP2: recCMP(shaderUnit, instruction); break;
case ShaderOpcodes::DP3: recDP3(shaderUnit, instruction); break;
case ShaderOpcodes::DP4: recDP4(shaderUnit, instruction); break;
// case ShaderOpcodes::DPH:
// case ShaderOpcodes::DPHI: recDPH(shaderUnit, instruction); break;
case ShaderOpcodes::DPH:
case ShaderOpcodes::DPHI: recDPH(shaderUnit, instruction); break;
case ShaderOpcodes::END: recEND(shaderUnit, instruction); break;
case ShaderOpcodes::EX2: recEX2(shaderUnit, instruction); break;
case ShaderOpcodes::FLR: recFLR(shaderUnit, instruction); break;
Expand Down Expand Up @@ -533,6 +533,39 @@ void ShaderEmitter::recDP4(const PICAShader& shader, u32 instruction) {
storeRegister(src1Vec, shader, dest, operandDescriptor);
}

void ShaderEmitter::recDPH(const PICAShader& shader, u32 instruction) {
const bool isDPHI = (instruction >> 26) == ShaderOpcodes::DPHI;

const u32 operandDescriptor = shader.operandDescriptors[instruction & 0x7f];
const u32 src1 = isDPHI ? getBits<14, 5>(instruction) : getBits<12, 7>(instruction);
const u32 src2 = isDPHI ? getBits<7, 7>(instruction) : getBits<7, 5>(instruction);
const u32 idx = getBits<19, 2>(instruction);
const u32 dest = getBits<21, 5>(instruction);
const u32 writeMask = getBits<0, 4>(operandDescriptor);

// TODO: Safe multiplication equivalent (Multiplication is not IEEE compliant on the PICA)
loadRegister<1>(src1Vec, shader, src1, isDPHI ? 0 : idx, operandDescriptor);
loadRegister<2>(src2Vec, shader, src2, isDPHI ? idx : 0, operandDescriptor);
// // Attach 1.0 to the w component of src1
MOV(src1Vec.Selem()[3], onesVector.Selem()[0]);

// Now perform a DP4
// Do a piecewise multiplication of the vectors first
if constexpr (useSafeMUL) {
emitSafeMUL(src1Vec, src2Vec, scratch1Vec);
} else {
FMUL(src1Vec.S4(), src1Vec.S4(), src2Vec.S4());
}
FADDP(src1Vec.S4(), src1Vec.S4(), src1Vec.S4()); // Now add the adjacent components together
FADDP(src1Vec.toS(), src1Vec.toD().S2()); // Again for the bottom 2 lanes. Now the bottom lane contains the dot product

if (writeMask != 0x8) { // Copy bottom lane to all lanes if we're not simply writing back x
DUP(src1Vec.S4(), src1Vec.Selem()[0]); // src1Vec = src1Vec.xxxx
}

storeRegister(src1Vec, shader, dest, operandDescriptor);
}

oaknut::Label ShaderEmitter::emitLog2Func() {
oaknut::Label funcStart;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class GlobalConfig {

public static DataModel data;

public static final Key<Boolean> KEY_SHADER_JIT = new Key<>("emu.shader_jit", false);
public static final Key<Boolean> KEY_SHADER_JIT = new Key<>("emu.shader_jit", true);
public static final Key<Boolean> KEY_PICTURE_IN_PICTURE = new Key<>("app.behavior.pictureInPicture", false);
public static final Key<Boolean> KEY_SHOW_PERFORMANCE_OVERLAY = new Key<>("dev.performanceOverlay", false);
public static final Key<Boolean> KEY_LOGGER_SERVICE = new Key<>("dev.loggerService", false);
Expand Down

0 comments on commit 1b071b6

Please sign in to comment.