Merge branch 'master' into shader-decomp

This commit is contained in:
wheremyfoodat 2024-08-23 22:14:48 +03:00
commit cf31f7b7e0
11 changed files with 946 additions and 5 deletions

View file

@ -71,6 +71,7 @@ void EmulatorConfig::load() {
forceShadergenForLights = toml::find_or<toml::boolean>(gpu, "ForceShadergenForLighting", true);
lightShadergenThreshold = toml::find_or<toml::integer>(gpu, "ShadergenLightThreshold", 1);
enableRenderdoc = toml::find_or<toml::boolean>(gpu, "EnableRenderdoc", false);
}
}
@ -142,6 +143,7 @@ void EmulatorConfig::save() {
data["GPU"]["ForceShadergenForLighting"] = forceShadergenForLights;
data["GPU"]["ShadergenLightThreshold"] = lightShadergenThreshold;
data["GPU"]["AccelerateShaders"] = accelerateShaders;
data["GPU"]["EnableRenderdoc"] = enableRenderdoc;
data["Audio"]["DSPEmulation"] = std::string(Audio::DSPCore::typeToString(dspType));
data["Audio"]["EnableAudio"] = audioEnabled;

View file

@ -194,7 +194,10 @@ void GPU::drawArrays() {
// Configures the type of primitive and the number of vertex shader outputs
const u32 primConfig = regs[PICA::InternalRegs::PrimitiveConfig];
const PICA::PrimType primType = static_cast<PICA::PrimType>(Helpers::getBits<8, 2>(primConfig));
if (vertexCount > Renderer::vertexBufferSize) Helpers::panic("[PICA] vertexCount > vertexBufferSize");
if (vertexCount > Renderer::vertexBufferSize) [[unlikely]] {
Helpers::warn("[PICA] vertexCount > vertexBufferSize");
return;
}
if ((primType == PICA::PrimType::TriangleList && vertexCount % 3) || (primType == PICA::PrimType::TriangleStrip && vertexCount < 3) ||
(primType == PICA::PrimType::TriangleFan && vertexCount < 3)) {

View file

@ -6,6 +6,8 @@
#include <fstream>
#include "renderdoc.hpp"
#ifdef _WIN32
#include <windows.h>
@ -32,6 +34,10 @@ Emulator::Emulator()
audioDevice.init(dsp->getSamples());
setAudioEnabled(config.audioEnabled);
if (Renderdoc::isSupported() && config.enableRenderdoc) {
loadRenderdoc();
}
#ifdef PANDA3DS_ENABLE_DISCORD_RPC
if (config.discordRpcEnabled) {
discordRpc.init();
@ -431,3 +437,9 @@ void Emulator::setAudioEnabled(bool enable) {
dsp->setAudioEnabled(enable);
}
void Emulator::loadRenderdoc() {
std::string capturePath = (std::filesystem::current_path() / "RenderdocCaptures").generic_string();
Renderdoc::loadRenderdoc();
Renderdoc::setOutputDir(capturePath, "");
}

View file

@ -1,9 +1,10 @@
#include "panda_sdl/frontend_sdl.hpp"
#include "version.hpp"
#include <glad/gl.h>
#include "renderdoc.hpp"
#include "sdl_sensors.hpp"
#include "version.hpp"
FrontendSDL::FrontendSDL() : keyboardMappings(InputMappings::defaultKeyboardMappings()) {
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0) {
@ -140,6 +141,14 @@ void FrontendSDL::run() {
emu.reset(Emulator::ReloadOption::Reload);
break;
}
case SDLK_F11: {
if constexpr (Renderdoc::isSupported()) {
Renderdoc::triggerCapture();
}
break;
}
}
}
break;

119
src/renderdoc.cpp Normal file
View file

@ -0,0 +1,119 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#ifdef PANDA3DS_ENABLE_RENDERDOC
#include "renderdoc.hpp"
#include <renderdoc_app.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#endif
#include <array>
#include <filesystem>
namespace Renderdoc {
enum class CaptureState {
Idle,
Triggered,
InProgress,
};
static CaptureState captureState{CaptureState::Idle};
RENDERDOC_API_1_6_0* rdocAPI{};
void loadRenderdoc() {
#ifdef WIN32
// Check if we are running in Renderdoc GUI
HMODULE mod = GetModuleHandleA("renderdoc.dll");
if (!mod) {
// If enabled in config, try to load RDoc runtime in offline mode
HKEY h_reg_key;
LONG result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Classes\\RenderDoc.RDCCapture.1\\DefaultIcon\\", 0, KEY_READ, &h_reg_key);
if (result != ERROR_SUCCESS) {
return;
}
std::array<wchar_t, MAX_PATH> keyString{};
DWORD stringSize{keyString.size()};
result = RegQueryValueExW(h_reg_key, L"", 0, NULL, (LPBYTE)keyString.data(), &stringSize);
if (result != ERROR_SUCCESS) {
return;
}
std::filesystem::path path{keyString.cbegin(), keyString.cend()};
path = path.parent_path().append("renderdoc.dll");
const auto path_to_lib = path.generic_string();
mod = LoadLibraryA(path_to_lib.c_str());
}
if (mod) {
const auto RENDERDOC_GetAPI = reinterpret_cast<pRENDERDOC_GetAPI>(GetProcAddress(mod, "RENDERDOC_GetAPI"));
const s32 ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_6_0, (void**)&rdocAPI);
if (ret != 1) {
Helpers::panic("Invalid return value from RENDERDOC_GetAPI");
}
}
#else
#ifdef ANDROID
static constexpr const char RENDERDOC_LIB[] = "libVkLayer_GLES_RenderDoc.so";
#else
static constexpr const char RENDERDOC_LIB[] = "librenderdoc.so";
#endif
if (void* mod = dlopen(RENDERDOC_LIB, RTLD_NOW | RTLD_NOLOAD)) {
const auto RENDERDOC_GetAPI = reinterpret_cast<pRENDERDOC_GetAPI>(dlsym(mod, "RENDERDOC_GetAPI"));
const s32 ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_6_0, (void**)&rdocAPI);
if (ret != 1) {
Helpers::panic("Invalid return value from RENDERDOC_GetAPI");
}
}
#endif
if (rdocAPI) {
// Disable default capture keys as they suppose to trigger present-to-present capturing
// and it is not what we want
rdocAPI->SetCaptureKeys(nullptr, 0);
// Also remove rdoc crash handler
rdocAPI->UnloadCrashHandler();
}
}
void startCapture() {
if (!rdocAPI) {
return;
}
if (captureState == CaptureState::Triggered) {
rdocAPI->StartFrameCapture(nullptr, nullptr);
captureState = CaptureState::InProgress;
}
}
void endCapture() {
if (!rdocAPI) {
return;
}
if (captureState == CaptureState::InProgress) {
rdocAPI->EndFrameCapture(nullptr, nullptr);
captureState = CaptureState::Idle;
}
}
void triggerCapture() {
if (captureState == CaptureState::Idle) {
captureState = CaptureState::Triggered;
}
}
void setOutputDir(const std::string& path, const std::string& prefix) {
if (rdocAPI) {
rdocAPI->SetCaptureFilePathTemplate((path + '\\' + prefix).c_str());
}
}
} // namespace Renderdoc
#endif