From 88426e0399849601c0e34b6f9848b76deba62234 Mon Sep 17 00:00:00 2001 From: "Daniel R." <47796739+polybiusproxy@users.noreply.github.com> Date: Fri, 12 Jul 2024 11:00:11 +0200 Subject: [PATCH] gnmdriver: Implement shader functions --- src/core/libraries/gnmdriver/gnmdriver.cpp | 141 +++++++++++++++++++-- src/core/libraries/gnmdriver/gnmdriver.h | 10 +- 2 files changed, 136 insertions(+), 15 deletions(-) diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index dcf6d99e..f057f4ed 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -1453,8 +1453,33 @@ s32 PS4_SYSV_ABI sceGnmSetEmbeddedVsShader(u32* cmdbuf, u32 size, u32 shader_id, return ORBIS_OK; } -int PS4_SYSV_ABI sceGnmSetEsShader() { - LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); +s32 PS4_SYSV_ABI sceGnmSetEsShader(u32* cmdbuf, u32 size, const u32* es_regs, u32 shader_modifier) { + LOG_TRACE(Lib_GnmDriver, "called"); + + if (!cmdbuf || size < 0x14) { + return -1; + } + + if (!es_regs) { + LOG_ERROR(Lib_GnmDriver, "Null pointer passed as argument"); + return -1; + } + + if (shader_modifier & 0xfcfffc3f) { + LOG_ERROR(Lib_GnmDriver, "Invalid modifier mask"); + return -1; + } + + if (es_regs[1] != 0) { + LOG_ERROR(Lib_GnmDriver, "Invalid shader address"); + return -1; + } + + const u32 var = shader_modifier == 0 ? es_regs[2] : (es_regs[2] & 0xfcfffc3f | shader_modifier); + cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0xc8u, es_regs[0], 0u); // SPI_SHADER_PGM_LO_ES + cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0xcau, var, es_regs[3]); // SPI_SHADER_PGM_RSRC1_ES + + WriteTrailingNop<11>(cmdbuf); return ORBIS_OK; } @@ -1463,18 +1488,91 @@ int PS4_SYSV_ABI sceGnmSetGsRingSizes() { return ORBIS_OK; } -int PS4_SYSV_ABI sceGnmSetGsShader() { - LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); +s32 PS4_SYSV_ABI sceGnmSetGsShader(u32* cmdbuf, u32 size, const u32* gs_regs) { + LOG_TRACE(Lib_GnmDriver, "called"); + + if (!cmdbuf || size < 0x1d) { + return -1; + } + + if (!gs_regs) { + LOG_ERROR(Lib_GnmDriver, "Null pointer passed as argument"); + return -1; + } + + if (gs_regs[1] != 0) { + LOG_ERROR(Lib_GnmDriver, "Invalid shader address"); + return -1; + } + + cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x88u, gs_regs[0], 0u); // SPI_SHADER_PGM_LO_GS + cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x8au, gs_regs[1], + gs_regs[1]); // SPI_SHADER_PGM_RSRC1_GS + + cmdbuf = PM4CmdSetData::SetContextReg(cmdbuf, 0x2e5u, gs_regs[4]); // VGT_STRMOUT_CONFIG + cmdbuf = PM4CmdSetData::SetContextReg(cmdbuf, 0x29bu, gs_regs[5]); // VGT_GS_OUT_PRIM_TYPE + cmdbuf = PM4CmdSetData::SetContextReg(cmdbuf, 0x2e4u, gs_regs[6]); // VGT_GS_INSTANCE_CNT + + WriteTrailingNop<11>(cmdbuf); return ORBIS_OK; } -int PS4_SYSV_ABI sceGnmSetHsShader() { - LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); +s32 PS4_SYSV_ABI sceGnmSetHsShader(u32* cmdbuf, u32 size, const u32* hs_regs, u32 param4) { + LOG_TRACE(Lib_GnmDriver, "called"); + + if (!cmdbuf || size < 0x1E) { + return -1; + } + + if (!hs_regs) { + LOG_ERROR(Lib_GnmDriver, "Null pointer passed as argument"); + return -1; + } + + if (hs_regs[1] != 0) { + LOG_ERROR(Lib_GnmDriver, "Invalid shader address"); + return -1; + } + + cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x108u, hs_regs[0], 0u); // SPI_SHADER_PGM_LO_HS + cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x10au, hs_regs[1], hs_regs[1]); // SPI_SHADER_PGM_RSRC1_HS + + cmdbuf = PM4CmdSetData::SetContextReg(cmdbuf, 0x286u, hs_regs[5], hs_regs[5]); // VGT_HOS_MAX_TESS_LEVEL + cmdbuf = PM4CmdSetData::SetContextReg(cmdbuf, 0x2dbu, hs_regs[4]); // VGT_TF_PARAM + cmdbuf = PM4CmdSetData::SetContextReg(cmdbuf, 0x2d6u, param4); // VGT_LS_HS_CONFIG + + WriteTrailingNop<11>(cmdbuf); return ORBIS_OK; } -int PS4_SYSV_ABI sceGnmSetLsShader() { - LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); +s32 PS4_SYSV_ABI sceGnmSetLsShader(u32* cmdbuf, u32 size, const u32* ls_regs, u32 shader_modifier) { + LOG_TRACE(Lib_GnmDriver, "called"); + + if (!cmdbuf || size < 0x17) { + return -1; + } + + if (!ls_regs) { + LOG_ERROR(Lib_GnmDriver, "Null pointer passed as argument"); + return -1; + } + + if (shader_modifier & 0xfcfffc3f) { + LOG_ERROR(Lib_GnmDriver, "Invalid modifier mask"); + return -1; + } + + if (ls_regs[1] != 0) { + LOG_ERROR(Lib_GnmDriver, "Invalid shader address"); + return -1; + } + + const u32 var = shader_modifier == 0 ? ls_regs[2] : (ls_regs[2] & 0xfcfffc3f | shader_modifier); + cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x148u, ls_regs[0], 0u); // SPI_SHADER_PGM_LO_LS + cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x14bu, ls_regs[3]); // SPI_SHADER_PGM_RSRC2_LS + cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x14au, var, ls_regs[3]); // SPI_SHADER_PGM_RSRC1_LS + + WriteTrailingNop<11>(cmdbuf); return ORBIS_OK; } @@ -2027,8 +2125,31 @@ int PS4_SYSV_ABI sceGnmUnregisterResource() { return ORBIS_OK; } -int PS4_SYSV_ABI sceGnmUpdateGsShader() { - LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); +s32 PS4_SYSV_ABI sceGnmUpdateGsShader(u32* cmdbuf, u32 size, const u32* gs_regs) { + LOG_TRACE(Lib_GnmDriver, "called"); + + if (!cmdbuf || size < 0x1d) { + return -1; + } + + if (!gs_regs) { + LOG_ERROR(Lib_GnmDriver, "Null pointer passed as argument"); + return -1; + } + + if (gs_regs[1] != 0) { + LOG_ERROR(Lib_GnmDriver, "Invalid shader address"); + return -1; + } + + cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x88u, gs_regs[0], 0u); // SPI_SHADER_PGM_LO_GS + cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x8au, gs_regs[1], gs_regs[1]); // SPI_SHADER_PGM_RSRC1_GS + + cmdbuf = WritePacket(cmdbuf, PM4ShaderType::ShaderGraphics, 0xc01e02e5u, gs_regs[4]); + cmdbuf = WritePacket(cmdbuf, PM4ShaderType::ShaderGraphics, 0xc01e029bu, gs_regs[5]); + cmdbuf = WritePacket(cmdbuf, PM4ShaderType::ShaderGraphics, 0xc01e02e4u, gs_regs[6]); + + WriteTrailingNop<11>(cmdbuf); return ORBIS_OK; } diff --git a/src/core/libraries/gnmdriver/gnmdriver.h b/src/core/libraries/gnmdriver/gnmdriver.h index 808cdf51..8100b116 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.h +++ b/src/core/libraries/gnmdriver/gnmdriver.h @@ -149,11 +149,11 @@ s32 PS4_SYSV_ABI sceGnmSetCsShaderWithModifier(u32* cmdbuf, u32 size, const u32* s32 PS4_SYSV_ABI sceGnmSetEmbeddedPsShader(u32* cmdbuf, u32 size, u32 shader_id, u32 shader_modifier); s32 PS4_SYSV_ABI sceGnmSetEmbeddedVsShader(u32* cmdbuf, u32 size, u32 shader_id, u32 modifier); -int PS4_SYSV_ABI sceGnmSetEsShader(); +s32 PS4_SYSV_ABI sceGnmSetEsShader(u32* cmdbuf, u32 size, const u32* es_regs, u32 shader_modifier); int PS4_SYSV_ABI sceGnmSetGsRingSizes(); -int PS4_SYSV_ABI sceGnmSetGsShader(); -int PS4_SYSV_ABI sceGnmSetHsShader(); -int PS4_SYSV_ABI sceGnmSetLsShader(); +s32 PS4_SYSV_ABI sceGnmSetGsShader(u32* cmdbuf, u32 size, const u32* gs_regs); +s32 PS4_SYSV_ABI sceGnmSetHsShader(u32* cmdbuf, u32 size, const u32* hs_regs, u32 param4); +s32 PS4_SYSV_ABI sceGnmSetLsShader(u32* cmdbuf, u32 size, const u32* ls_regs, u32 shader_modifier); s32 PS4_SYSV_ABI sceGnmSetPsShader(u32* cmdbuf, u32 size, const u32* ps_regs); s32 PS4_SYSV_ABI sceGnmSetPsShader350(u32* cmdbuf, u32 size, const u32* ps_regs); int PS4_SYSV_ABI sceGnmSetResourceRegistrationUserMemory(); @@ -216,7 +216,7 @@ int PS4_SYSV_ABI sceGnmUnmapComputeQueue(); int PS4_SYSV_ABI sceGnmUnregisterAllResourcesForOwner(); int PS4_SYSV_ABI sceGnmUnregisterOwnerAndResources(); int PS4_SYSV_ABI sceGnmUnregisterResource(); -int PS4_SYSV_ABI sceGnmUpdateGsShader(); +s32 PS4_SYSV_ABI sceGnmUpdateGsShader(u32* cmdbuf, u32 size, const u32* gs_regs); int PS4_SYSV_ABI sceGnmUpdateHsShader(); s32 PS4_SYSV_ABI sceGnmUpdatePsShader(u32* cmdbuf, u32 size, const u32* ps_regs); s32 PS4_SYSV_ABI sceGnmUpdatePsShader350(u32* cmdbuf, u32 size, const u32* ps_regs);