mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
riscv: Initial vertexjit.
This commit is contained in:
1 parent
0b05d20c0a
commit
219e0db4e5
5 files changed
+164
No files matched your search
@@ -1485,6 +1485,10 @@ list(APPEND CoreExtra
|
||||
Core/MIPS/MIPS/MipsJit.h
|
||||
)
|
||||
|
||||
list(APPEND CoreExtra
|
||||
GPU/Common/VertexDecoderRiscV.cpp
|
||||
)
|
||||
|
||||
if(NOT MOBILE_DEVICE)
|
||||
set(CoreExtra ${CoreExtra}
|
||||
Core/AVIDump.cpp
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
#include "Common/Arm64Emitter.h"
|
||||
#elif PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64)
|
||||
#include "Common/x64Emitter.h"
|
||||
#elif PPSSPP_ARCH(RISCV64)
|
||||
#include "Common/RiscVEmitter.h"
|
||||
#else
|
||||
#include "Common/FakeEmitter.h"
|
||||
#endif
|
||||
@@ -489,6 +491,8 @@ public:
|
||||
#define VERTEXDECODER_JIT_BACKEND Arm64Gen::ARM64CodeBlock
|
||||
#elif PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64)
|
||||
#define VERTEXDECODER_JIT_BACKEND Gen::XCodeBlock
|
||||
#elif PPSSPP_ARCH(RISCV64)
|
||||
#define VERTEXDECODER_JIT_BACKEND RiscVGen::RiscVCodeBlock
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
// Copyright (c) 2023- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "ppsspp_config.h"
|
||||
#if PPSSPP_ARCH(RISCV64)
|
||||
|
||||
#include "Common/CPUDetect.h"
|
||||
#include "Common/Log.h"
|
||||
#include "Common/RiscVEmitter.h"
|
||||
#include "Core/MIPS/JitCommon/JitCommon.h"
|
||||
#include "GPU/GPUState.h"
|
||||
#include "GPU/Common/VertexDecoderCommon.h"
|
||||
|
||||
using namespace RiscVGen;
|
||||
|
||||
static const RiscVReg srcReg = X10;
|
||||
static const RiscVReg dstReg = X11;
|
||||
static const RiscVReg counterReg = X12;
|
||||
|
||||
static const RiscVReg tempReg1 = X13;
|
||||
static const RiscVReg tempReg2 = X14;
|
||||
static const RiscVReg tempReg3 = X15;
|
||||
static const RiscVReg scratchReg = X16;
|
||||
|
||||
static const RiscVReg fullAlphaReg = X17;
|
||||
static const RiscVReg boundsMinUReg = X28;
|
||||
static const RiscVReg boundsMinVReg = X29;
|
||||
static const RiscVReg boundsMaxUReg = X30;
|
||||
static const RiscVReg boundsMaxVReg = X31;
|
||||
|
||||
static const RiscVReg fpScratchReg1 = F10;
|
||||
static const RiscVReg fpScratchReg2 = F11;
|
||||
static const RiscVReg fpScratchReg3 = F12;
|
||||
static const RiscVReg fpScratchReg4 = F13;
|
||||
|
||||
static const JitLookup jitLookup[] = {
|
||||
{&VertexDecoder::Step_TcFloat, &VertexDecoderJitCache::Jit_TcFloat},
|
||||
};
|
||||
|
||||
JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int32_t *jittedSize) {
|
||||
dec_ = &dec;
|
||||
|
||||
BeginWrite(4096);
|
||||
const u8 *start = AlignCode16();
|
||||
SetAutoCompress(true);
|
||||
|
||||
bool log = false;
|
||||
|
||||
if (dec.col) {
|
||||
// Or LDB and skip the conditional? This is probably cheaper.
|
||||
LI(fullAlphaReg, 0xFF);
|
||||
}
|
||||
|
||||
if (dec.tc && dec.throughmode) {
|
||||
// TODO: Smarter, only when doing bounds.
|
||||
LI(tempReg1, &gstate_c.vertBounds.minU);
|
||||
LH(boundsMinUReg, tempReg1, offsetof(KnownVertexBounds, minU));
|
||||
LH(boundsMaxUReg, tempReg1, offsetof(KnownVertexBounds, maxU));
|
||||
LH(boundsMinVReg, tempReg1, offsetof(KnownVertexBounds, minV));
|
||||
LH(boundsMaxVReg, tempReg1, offsetof(KnownVertexBounds, maxV));
|
||||
}
|
||||
|
||||
// TODO: Skipping, prescale.
|
||||
|
||||
const u8 *loopStart = GetCodePtr();
|
||||
for (int i = 0; i < dec.numSteps_; i++) {
|
||||
if (!CompileStep(dec, i)) {
|
||||
EndWrite();
|
||||
// Reset the code ptr (effectively undoing what we generated) and return zero to indicate that we failed.
|
||||
ResetCodePtr(GetOffset(start));
|
||||
char temp[1024]{};
|
||||
dec.ToString(temp);
|
||||
ERROR_LOG(G3D, "Could not compile vertex decoder, failed at step %d: %s", i, temp);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ADDI(srcReg, srcReg, dec.VertexSize());
|
||||
ADDI(dstReg, dstReg, dec.decFmt.stride);
|
||||
ADDI(counterReg, counterReg, -1);
|
||||
BLT(R_ZERO, counterReg, loopStart);
|
||||
|
||||
if (dec.col) {
|
||||
LI(tempReg1, &gstate_c.vertexFullAlpha);
|
||||
FixupBranch skip = BNE(R_ZERO, fullAlphaReg);
|
||||
SB(fullAlphaReg, tempReg1, 0);
|
||||
SetJumpTarget(skip);
|
||||
}
|
||||
|
||||
if (dec.tc && dec.throughmode) {
|
||||
// TODO: Smarter, only when doing bounds.
|
||||
LI(tempReg1, &gstate_c.vertBounds.minU);
|
||||
SH(boundsMinUReg, tempReg1, offsetof(KnownVertexBounds, minU));
|
||||
SH(boundsMaxUReg, tempReg1, offsetof(KnownVertexBounds, maxU));
|
||||
SH(boundsMinVReg, tempReg1, offsetof(KnownVertexBounds, minV));
|
||||
SH(boundsMaxVReg, tempReg1, offsetof(KnownVertexBounds, maxV));
|
||||
}
|
||||
|
||||
RET();
|
||||
|
||||
FlushIcache();
|
||||
|
||||
if (log) {
|
||||
char temp[1024]{};
|
||||
dec.ToString(temp);
|
||||
INFO_LOG(JIT, "=== %s (%d bytes) ===", temp, (int)(GetCodePtr() - start));
|
||||
std::vector<std::string> lines = DisassembleRV64(start, (int)(GetCodePtr() - start));
|
||||
for (auto line : lines) {
|
||||
INFO_LOG(JIT, "%s", line.c_str());
|
||||
}
|
||||
INFO_LOG(JIT, "==========");
|
||||
}
|
||||
|
||||
*jittedSize = (int)(GetCodePtr() - start);
|
||||
EndWrite();
|
||||
return (JittedVertexDecoder)start;
|
||||
}
|
||||
|
||||
bool VertexDecoderJitCache::CompileStep(const VertexDecoder &dec, int step) {
|
||||
// See if we find a matching JIT function.
|
||||
for (size_t i = 0; i < ARRAY_SIZE(jitLookup); i++) {
|
||||
if (dec.steps_[step] == jitLookup[i].func) {
|
||||
((*this).*jitLookup[i].jitFunc)();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_TcFloat() {
|
||||
// Just copy 64 bits. Might be nice if we could detect misaligned load perf.
|
||||
LW(tempReg1, srcReg, dec_->tcoff);
|
||||
LW(tempReg2, srcReg, dec_->tcoff + 4);
|
||||
SW(tempReg1, dstReg, dec_->decFmt.uvoff);
|
||||
SW(tempReg2, dstReg, dec_->decFmt.uvoff + 4);
|
||||
}
|
||||
|
||||
#endif // PPSSPP_ARCH(RISCV64)
|
||||
@@ -498,6 +498,7 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Common\VertexDecoderCommon.cpp" />
|
||||
<ClCompile Include="Common\VertexDecoderRiscV.cpp" />
|
||||
<ClCompile Include="Common\VertexDecoderX86.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</ExcludedFromBuild>
|
||||
|
||||
@@ -521,6 +521,9 @@
|
||||
<ClCompile Include="GLES\StencilBufferGLES.cpp">
|
||||
<Filter>GLES</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Common\VertexDecoderRiscV.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<FxCompile Include="..\assets\shaders\tex_4xbrz.csh">
|
||||
|
||||
Reference in new issue
Block a user