From 415e276ef9789b02532232f69b2369525653fb36 Mon Sep 17 00:00:00 2001 From: wheremyfoodat Date: Thu, 8 Jun 2023 18:51:03 +0300 Subject: [PATCH] [Shader JIT] Moar --- CMakeLists.txt | 3 ++- include/PICA/dynapica/shader_rec.hpp | 9 ++++++-- .../PICA/dynapica/shader_rec_emitter_x64.hpp | 23 +++++++++++++++++++ include/PICA/shader.hpp | 7 ++++-- src/core/PICA/dynapica/shader_rec.cpp | 6 ++--- .../PICA/dynapica/shader_rec_emitter_x64.cpp | 11 +++++++++ .../dynapica/shader_rec_instructions_x64.cpp | 0 7 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 include/PICA/dynapica/shader_rec_emitter_x64.hpp create mode 100644 src/core/PICA/dynapica/shader_rec_emitter_x64.cpp delete mode 100644 src/core/PICA/dynapica/shader_rec_instructions_x64.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f69b5d85..ed3d298c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,7 +94,7 @@ set(SERVICE_SOURCE_FILES src/core/services/service_manager.cpp src/core/services ) set(PICA_SOURCE_FILES src/core/PICA/gpu.cpp src/core/PICA/regs.cpp src/core/PICA/shader_unit.cpp src/core/PICA/shader_interpreter.cpp src/core/PICA/dynapica/shader_rec.cpp - src/core/PICA/dynapica/shader_rec_instructions_x64.cpp + src/core/PICA/dynapica/shader_rec_emitter_x64.cpp ) set(RENDERER_GL_SOURCE_FILES src/core/renderer_gl/renderer_gl.cpp src/core/renderer_gl/textures.cpp src/core/renderer_gl/etc1.cpp) @@ -124,6 +124,7 @@ set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/opengl.hpp inc include/services/ldr_ro.hpp include/ipc.hpp include/services/act.hpp include/services/nfc.hpp include/system_models.hpp include/services/dlp_srvr.hpp include/PICA/dynapica/pica_recs.hpp include/PICA/dynapica/x64_regs.hpp include/PICA/dynapica/vertex_loader_rec.hpp include/PICA/dynapica/shader_rec.hpp + include/PICA/dynapica/shader_rec_emitter_x64.hpp ) set(THIRD_PARTY_SOURCE_FILES third_party/imgui/imgui.cpp diff --git a/include/PICA/dynapica/shader_rec.hpp b/include/PICA/dynapica/shader_rec.hpp index 09ff5664..9aa97947 100644 --- a/include/PICA/dynapica/shader_rec.hpp +++ b/include/PICA/dynapica/shader_rec.hpp @@ -7,8 +7,7 @@ #include #ifdef PANDA3DS_X64_HOST -#include "xbyak/xbyak.h" -using ShaderEmitter = Xbyak::CodeGenerator; +#include "shader_rec_emitter_x64.hpp" #endif #endif @@ -16,6 +15,7 @@ class ShaderJIT { #ifdef PANDA3DS_SHADER_JIT_SUPPORTED using Hash = PICAShader::Hash; using ShaderCache = std::unordered_map>; + ShaderEmitter::Callback activeShaderCallback; ShaderCache cache; void compileShader(PICAShader& shaderUnit); @@ -35,8 +35,13 @@ public: Helpers::panic("Vertex Loader JIT: Tried to load vertices with JIT on platform that does not support vertex loader jit"); } + // Define dummy callback. This should never be called if the shader JIT is not supported + using Callback = void(*)(PICAShader& shaderUnit); + Callback activeShaderCallback = nullptr; + void reset() {} static constexpr bool isAvailable() { return false; } #endif + auto getCallback() { return activeShaderCallback; } }; \ No newline at end of file diff --git a/include/PICA/dynapica/shader_rec_emitter_x64.hpp b/include/PICA/dynapica/shader_rec_emitter_x64.hpp new file mode 100644 index 00000000..b4022587 --- /dev/null +++ b/include/PICA/dynapica/shader_rec_emitter_x64.hpp @@ -0,0 +1,23 @@ +#pragma once + +// Only do anything if we're on an x64 target with JIT support enabled +#if defined(PANDA3DS_DYNAPICA_SUPPORTED) && defined(PANDA3DS_X64_HOST) +#include "helpers.hpp" +#include "PICA/shader.hpp" +#include "xbyak/xbyak.h" +#include "x64_regs.hpp" + +class ShaderEmitter : public Xbyak::CodeGenerator { + static constexpr size_t executableMemorySize = PICAShader::maxInstructionCount * 96; // How much executable memory to alloc for each shader + // Allocate some extra space as padding for security purposes in the extremely unlikely occasion we manage to overflow the above size + static constexpr size_t allocSize = executableMemorySize + 0x1000; + +public: + using Callback = void(*)(const PICAShader& shaderUnit); + + // Initialize our emitter with "allocSize" bytes of RWX memory + ShaderEmitter() : Xbyak::CodeGenerator(allocSize) {} + void compile(const PICAShader& shaderUnit); +}; + +#endif // x64 recompiler check \ No newline at end of file diff --git a/include/PICA/shader.hpp b/include/PICA/shader.hpp index 6f3d62f8..a2f830b1 100644 --- a/include/PICA/shader.hpp +++ b/include/PICA/shader.hpp @@ -100,7 +100,9 @@ protected: bool codeHashDirty = false; bool opdescHashDirty = false; + // Add these as friend classes for the JIT so it has access to all important state friend class ShaderJIT; + friend class ShaderEmitter; private: vec4f getSource(u32 source); @@ -184,8 +186,9 @@ private: bool isCondTrue(u32 instruction); public: - std::array loadedShader; // Currently loaded & active shader - std::array bufferedShader; // Shader to be transferred when the SH_CODETRANSFER_END reg gets written to + static constexpr size_t maxInstructionCount = 4096; + std::array loadedShader; // Currently loaded & active shader + std::array bufferedShader; // Shader to be transferred when the SH_CODETRANSFER_END reg gets written to u32 entrypoint = 0; // Initial shader PC u32 boolUniform; diff --git a/src/core/PICA/dynapica/shader_rec.cpp b/src/core/PICA/dynapica/shader_rec.cpp index e5a08caa..3029c0e2 100644 --- a/src/core/PICA/dynapica/shader_rec.cpp +++ b/src/core/PICA/dynapica/shader_rec.cpp @@ -7,6 +7,7 @@ void ShaderJIT::reset() { } void ShaderJIT::prepare(PICAShader& shaderUnit) { + shaderUnit.pc = shaderUnit.entrypoint; // We construct a shader hash from both the code and operand descriptor hashes // This is so that if only one of them changes, we still properly recompile the shader // This code is inspired from how Citra solves this problem @@ -15,11 +16,10 @@ void ShaderJIT::prepare(PICAShader& shaderUnit) { if (it == cache.end()) { // Block has not been compiled yet auto emitter = std::make_unique(); + emitter->compile(shaderUnit); cache.emplace_hint(it, hash, std::move(emitter)); } else { // Block has been compiled and found, use it - + auto emitter = it->second.get(); } - - shaderUnit.pc = shaderUnit.entrypoint; } #endif // PANDA3DS_SHADER_JIT_SUPPORTED \ No newline at end of file diff --git a/src/core/PICA/dynapica/shader_rec_emitter_x64.cpp b/src/core/PICA/dynapica/shader_rec_emitter_x64.cpp new file mode 100644 index 00000000..0511cd95 --- /dev/null +++ b/src/core/PICA/dynapica/shader_rec_emitter_x64.cpp @@ -0,0 +1,11 @@ +#if defined(PANDA3DS_DYNAPICA_SUPPORTED) && defined(PANDA3DS_X64_HOST) +#include "PICA/dynapica/shader_rec_emitter_x64.hpp" + +using namespace Xbyak; +using namespace Xbyak::util; + +void ShaderEmitter::compile(const PICAShader& shaderUnit) { + +} + +#endif \ No newline at end of file diff --git a/src/core/PICA/dynapica/shader_rec_instructions_x64.cpp b/src/core/PICA/dynapica/shader_rec_instructions_x64.cpp deleted file mode 100644 index e69de29b..00000000