From f21b7bd3ff2555987316662c7d2a1d5a58a14225 Mon Sep 17 00:00:00 2001 From: Dima353 <75039669+Dima353@users.noreply.github.com> Date: Sun, 26 Jul 2026 13:47:11 +0300 Subject: [PATCH] Vita: modern-librw render path + enable Neo pipelines --- .github/workflows/build-vita.yml | 2 +- Makefile | 2 +- src/core/Game.cpp | 9 ----- src/core/MenuScreensCustom.cpp | 8 ++-- src/core/config.h | 8 ++-- src/core/main.cpp | 38 +++++++++---------- src/core/re3.cpp | 4 ++ src/extras/postfx.cpp | 63 +++----------------------------- src/fakerw/fake.cpp | 28 -------------- src/renderer/ShadowCamera.cpp | 6 +-- src/rw/TexRead.cpp | 8 ++-- src/skel/glfw/MoviePlayer.cpp | 1 + 12 files changed, 43 insertions(+), 134 deletions(-) diff --git a/.github/workflows/build-vita.yml b/.github/workflows/build-vita.yml index 4239bd67..f8aff695 100644 --- a/.github/workflows/build-vita.yml +++ b/.github/workflows/build-vita.yml @@ -35,7 +35,7 @@ jobs: - name: Build vitaGL run: | git clone --depth 1 https://github.com/Rinnegatamante/vitaGL.git - make -C vitaGL NO_DEBUG=1 PHYCONT_ON_DEMAND=1 ENABLE_LEGACY_PIPELINE=1 -j"$(nproc)" install + make -C vitaGL NO_DEBUG=1 PHYCONT_ON_DEMAND=1 ENABLE_LEGACY_PIPELINE=1 HAVE_SHADER_CACHE=1 NO_SPLASHSCREEN=1 -j"$(nproc)" install - name: Build librw-vita (fork, kept building against current vitaGL) run: | diff --git a/Makefile b/Makefile index 33160c63..a015cc7b 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ CC = $(PREFIX)-gcc CXX = $(PREFIX)-g++ ARCH := -mtune=cortex-a9 -march=armv7-a -mfpu=neon CFLAGS := -g -Wl,-q,--no-enum-size-warning -fno-short-enums -fno-optimize-sibling-calls -O2 -ftree-vectorize -mfloat-abi=hard -fno-builtin-memcpy $(ARCH) $(DEFINES) -CFLAGS += $(INCLUDE) -DPSP2 -DNDEBUG -DMASTER -DLIBRW -DRW_GL3 -DAUDIO_OAL -DLIBRW_GLAD +CFLAGS += $(INCLUDE) -DPSP2 -DMASTER -DLIBRW -DRW_GL3 -DAUDIO_OAL -DLIBRW_GLAD CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions ASFLAGS := -g $(ARCH) LDFLAGS = -g $(ARCH) -Wl,-Map,$(notdir $*.map) diff --git a/src/core/Game.cpp b/src/core/Game.cpp index c0001626..77c8965f 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -244,14 +244,6 @@ CGame::InitialiseRenderWare(void) CreateDebugFont(); #ifdef LIBRW -// librw-vita predates the envMap* knobs and only exposes modulateEnvMap. -#ifdef PSP2 -#ifdef PS2_MATFX - rw::MatFX::modulateEnvMap = true; -#else - rw::MatFX::modulateEnvMap = false; -#endif -#else #ifdef PS2_MATFX rw::MatFX::envMapApplyLight = true; rw::MatFX::envMapUseMatColor = true; @@ -263,7 +255,6 @@ CGame::InitialiseRenderWare(void) #endif rw::RGBA envcol = { 64, 64, 64, 255 }; rw::MatFX::envMapColor = envcol; -#endif #else #ifdef PS2_MATFX ReplaceMatFxCallback(); diff --git a/src/core/MenuScreensCustom.cpp b/src/core/MenuScreensCustom.cpp index 0190b705..0f464203 100644 --- a/src/core/MenuScreensCustom.cpp +++ b/src/core/MenuScreensCustom.cpp @@ -67,10 +67,10 @@ extern bool useRearpad; // touch input: front panel or rear, see crossplatform.c #define FREE_CAM_TOGGLE #endif -#ifdef PS2_ALPHA_TEST +#if defined(PS2_ALPHA_TEST) && !defined(PSP2) #define DUALPASS_SELECTOR MENUACTION_CFO_SELECT, "FEM_2PR", { new CCFOSelect((int8*)&gPS2alphaTest, "Graphics", "PS2AlphaTest", off_on, 2, false) }, 0, 0, MENUALIGN_LEFT, #else - #define DUALPASS_SELECTOR + #define DUALPASS_SELECTOR #endif #ifdef PED_CAR_DENSITY_SLIDERS @@ -115,8 +115,8 @@ void RestoreDefGraphics(int8 action) { if (action != FEOPTION_ACTION_SELECT) return; - #ifdef PS2_ALPHA_TEST - gPS2alphaTest = false; + #if defined(PS2_ALPHA_TEST) && !defined(PSP2) + gPS2alphaTest = false; // PSP2: kept forced-on, no menu toggle #endif #ifdef MULTISAMPLING FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel = 0; diff --git a/src/core/config.h b/src/core/config.h index df114595..fef5587c 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -349,15 +349,13 @@ enum Config { //#define USE_TEXTURE_POOL #ifdef LIBRW #define EXTENDED_COLOURFILTER // more options for colour filter (replaces mblur) -// Not on PSP2: librw-vita is an old fork with no setupVertexInput, no three-argument -// Shader::create and no UNIFORM_VEC4, so the Neo pipelines and the droplets cannot -// build against it. They would also need Cg versions of every shader. -#ifndef PSP2 +// librw-vita is now the modern fork, so these build on PSP2 as well. Runtime defaults: +// NEW_RENDERER is on (gbNewRenderer, PSP2), the Neo pipeline stays MATFX (stock look, +// opt-in via the graphics menu), and SCREEN_DROPLETS only shows in rain. #define EXTENDED_PIPELINES // custom render pipelines (includes Neo) #define SCREEN_DROPLETS // neo water droplets #define NEW_RENDERER // leeds-like world rendering, needs librw #endif -#endif #define FIX_SPRITES // fix sprites aspect ratio(moon, coronas, particle etc) diff --git a/src/core/main.cpp b/src/core/main.cpp index 646d87bf..4ceeadd2 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -135,8 +135,12 @@ bool gbPrintMemoryUsage; #endif #ifdef NEW_RENDERER +#ifdef PSP2 +bool gbNewRenderer = true; +#else bool gbNewRenderer; #endif +#endif #ifdef FIX_BUGS // need to clear stencil for mblur fx. no idea why it works in the original game // also for clearing out water rects in new renderer @@ -355,11 +359,6 @@ RwGrabScreen(RwCamera *camera, RwChar *filename) #define TILE_WIDTH 576 #define TILE_HEIGHT 432 -#ifdef PSP2 -extern GLuint fxfb; -bool using_fbo = false; -#endif - void DoRWStuffEndOfFrame(void) { @@ -368,18 +367,6 @@ DoRWStuffEndOfFrame(void) FlushObrsPrintfs(); RwCameraEndUpdate(Scene.camera); -#if defined(PSP2) && defined(EXTENDED_COLOURFILTER) - // Arm the next frame's capture: bind our FBO once CPostFX has asked for it, so - // the scene renders into fxraster and the colour filter can sample it. - if(CPostFX::NeedBackBuffer()){ - if (using_fbo) { - glBindFramebuffer(GL_FRAMEBUFFER, fxfb); - using_fbo = false; - } else - glBindFramebuffer(GL_FRAMEBUFFER, 0); - } -#endif - RsCameraShowRaster(Scene.camera); #ifndef MASTER char s[48]; @@ -1632,14 +1619,23 @@ Idle(void *arg) RwCameraSetFogDistance(Scene.camera, CTimeCycle::GetFogStart()); #endif +#ifdef EXTENDED_PIPELINES + // Render the env-map reflection BEFORE the main scene, not after. On the Vita + // tile-based GPU the env-map RTT (a render-target switch with its own depth) + // left the depth-dependent late passes (coronas, shadows, glints) rendering + // against a disturbed state, so they showed through geometry. Doing it first + // makes RenderScene the last thing to touch the display + depth, so those + // passes see a clean scene. Also removes the one-frame lag on car reflections. + CustomPipes::EnvMapRender(); + // EnvMapRender leaves render state from the reflection pass; reset it so the + // main scene (and the depth-dependent passes after it) start clean. + DefinedState(); +#endif + tbStartTimer(0, "RenderScene"); RenderScene(); tbEndTimer("RenderScene"); -#ifdef EXTENDED_PIPELINES - CustomPipes::EnvMapRender(); -#endif - RenderDebugShit(); RenderEffects(); diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 11758fd7..c88042b9 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -142,13 +142,17 @@ CustomFrontendOptionsPopulate(void) FrontendOptionSetCursor(MENUPAGE_GRAPHICS_SETTINGS, -3, false); FrontendOptionAddSelect("FED_VPL", 0, 0, MENUALIGN_LEFT, vehPipelineNames, ARRAY_SIZE(vehPipelineNames), (int8*)&CustomPipes::VehiclePipeSwitch, false, nil, "Graphics", "VehiclePipeline"); FrontendOptionAddSelect("FED_PRM", 0, 0, MENUALIGN_LEFT, off_on, 2, (int8*)&CustomPipes::RimlightEnable, false, nil, "Graphics", "NeoRimLight"); +#ifndef PSP2 // World Lightmaps need Xbox neo resources (absent in PC data) - hide on Vita FrontendOptionAddSelect("FED_WLM", 0, 0, MENUALIGN_LEFT, off_on, 2, (int8*)&CustomPipes::LightmapEnable, false, nil, "Graphics", "NeoLightMaps"); +#endif FrontendOptionAddSelect("FED_RGL", 0, 0, MENUALIGN_LEFT, off_on, 2, (int8*)&CustomPipes::GlossEnable, false, nil, "Graphics", "NeoRoadGloss"); #else FrontendOptionSetCursor(MENUPAGE_DISPLAY_SETTINGS, -3, false); FrontendOptionAddSelect("FED_VPL", 0, 0, MENUALIGN_LEFT, vehPipelineNames, ARRAY_SIZE(vehPipelineNames), (int8*)&CustomPipes::VehiclePipeSwitch, false, nil, "Graphics", "VehiclePipeline"); FrontendOptionAddSelect("FED_PRM", 0, 0, MENUALIGN_LEFT, off_on, 2, (int8*)&CustomPipes::RimlightEnable, false, nil, "Graphics", "NeoRimLight"); +#ifndef PSP2 // World Lightmaps need Xbox neo resources (absent in PC data) - hide on Vita FrontendOptionAddSelect("FED_WLM", 0, 0, MENUALIGN_LEFT, off_on, 2, (int8*)&CustomPipes::LightmapEnable, false, nil, "Graphics", "NeoLightMaps"); +#endif FrontendOptionAddSelect("FED_RGL", 0, 0, MENUALIGN_LEFT, off_on, 2, (int8*)&CustomPipes::GlossEnable, false, nil, "Graphics", "NeoRoadGloss"); #endif CFileMgr::CloseFile(fd); diff --git a/src/extras/postfx.cpp b/src/extras/postfx.cpp index 3782a9cc..704463ae 100644 --- a/src/extras/postfx.cpp +++ b/src/extras/postfx.cpp @@ -13,13 +13,6 @@ #include "MBlur.h" #include "postfx.h" -#ifdef PSP2 -// The Vita captures the scene into its own FBO instead of reading the backbuffer: -// see DoRWStuffEndOfFrame, which flips the binding a frame ahead. -GLuint fxraster = 0xDEADBEEF, fxfb; -extern bool using_fbo; -#endif - RwRaster *CPostFX::pFrontBuffer; RwRaster *CPostFX::pBackBuffer; bool CPostFX::bJustInitialised; @@ -169,43 +162,27 @@ CPostFX::Open(RwCamera *cam) contrast_PS = rw::d3d::createPixelShader(contrastPS_cso); #endif #ifdef RW_OPENGL -#ifdef PSP2 - // Cg source, not the precompiled GXP blobs: librw-vita is built with - // PSP2_USE_SHADER_COMPILER, so Shader::create expects source strings, and - // glShaderBinary would now be handed a blob it cannot parse. - #include "shaders/im2d_v_cg.inc" -#endif + // The Vita used to take a separate path here: Cg sources and librw-vita's + // 3-argument Shader::create(vs, fs, is_2d). Modern librw has neither, so it + // goes through the common GLSL path; vitaGL's GLSL translator understands the + // attribute/varying dialect that shaderDecl100es emits. using namespace rw::gl3; { -#ifdef PSP2 -#include "shaders/colourfilterVC_f_cg.inc" - const char *vs[] = { im2d_v_cg_src, nil }; - const char *fs[] = { colourfilterVC_f_cg_src, nil }; - colourFilterVC = Shader::create(vs, fs, true); -#else #include "shaders/obj/im2d_vert.inc" #include "shaders/obj/colourfilterVC_frag.inc" const char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil }; const char *fs[] = { shaderDecl, header_frag_src, colourfilterVC_frag_src, nil }; colourFilterVC = Shader::create(vs, fs); -#endif assert(colourFilterVC); } { -#ifdef PSP2 -#include "shaders/contrast_f_cg.inc" - const char *vs[] = { im2d_v_cg_src, nil }; - const char *fs[] = { contrast_f_cg_src, nil }; - contrast = Shader::create(vs, fs, true); -#else #include "shaders/obj/im2d_vert.inc" #include "shaders/obj/contrast_frag.inc" const char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil }; const char *fs[] = { shaderDecl, header_frag_src, contrast_frag_src, nil }; contrast = Shader::create(vs, fs); -#endif assert(contrast); } @@ -342,14 +319,8 @@ CPostFX::RenderOverlayShader(RwCamera *cam, int32 r, int32 g, int32 b, int32 a) glUniform4fv(colourFilterVC->uniformLocations[u_blurcolor], 1, blurcolors); #endif } -#ifdef PSP2 - // The scene lives in our own FBO texture here, not in pBackBuffer. - glBindTexture(GL_TEXTURE_2D, fxraster); - RwIm2DVertexSetIntRGBA(&Vertex[0], 255, 255, 255, 255); - RwIm2DVertexSetIntRGBA(&Vertex[1], 255, 255, 255, 255); - RwIm2DVertexSetIntRGBA(&Vertex[2], 255, 255, 255, 255); - RwIm2DVertexSetIntRGBA(&Vertex[3], 255, 255, 255, 255); -#endif + // Vita now captures via GetBackBuffer (glBlitFramebuffer in librw's + // rasterRenderFast) into pBackBuffer, sampled through the texture raster set above. RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6); #ifdef RW_D3D9 rw::d3d::im2dOverridePS = nil; @@ -463,11 +434,8 @@ CPostFX::Render(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blu blur = AvgAlpha; } - // PSP2 captures the scene through its own FBO a frame ahead instead. -#ifndef PSP2 if(NeedBackBuffer()) GetBackBuffer(cam); -#endif DefinedState(); @@ -480,25 +448,6 @@ CPostFX::Render(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blu if(!bJustInitialised) RenderOverlaySniper(cam, red, green, blue, blur); }else{ -#if defined(PSP2) && defined(EXTENDED_COLOURFILTER) - // Arm the capture for the next frame: DoRWStuffEndOfFrame binds fxfb once - // using_fbo is set, so the scene lands in fxraster and this pass samples it. - if (NeedBackBuffer()) { - if(fxraster == 0xDEADBEEF){ - glGenTextures(1, &fxraster); - glBindTexture(GL_TEXTURE_2D, fxraster); - // Screen-sized, not a POT block: the fullscreen quad samples this - // over 0..1, so anything bigger leaves the scene in a sub-rect and - // the remainder reads as black. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 960, 544, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - glGenFramebuffers(1, &fxfb); - glBindFramebuffer(GL_FRAMEBUFFER, fxfb); - glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fxraster, 0); - } - using_fbo = true; - glBindFramebuffer(GL_FRAMEBUFFER, 0); - } -#endif switch(EffectSwitch){ case POSTFX_OFF: case POSTFX_SIMPLE: diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index 38447751..a972e309 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -299,40 +299,12 @@ RwTextureAddressMode RwTextureGetAddressingV(const RwTexture *texture); // TODO void _rwD3D8TexDictionaryEnableRasterFormatConversion(bool enable) { } -#ifdef PSP2 -// librw-vita predates Raster::convertTexToCurrentPlatform, so do it by hand: -// round-trip through an Image, which also drops the palette the Vita cannot use. -static rw::Raster* -ConvertTexRaster(rw::Raster *ras) -{ - using namespace rw; - - if(ras->platform == rw::platform) - return ras; - // compatible platforms - if(ras->platform == PLATFORM_D3D8 && rw::platform == PLATFORM_D3D9 || - ras->platform == PLATFORM_D3D9 && rw::platform == PLATFORM_D3D8) - return ras; - - Image *img = ras->toImage(); - ras->destroy(); - img->unpalettize(); - ras = Raster::createFromImage(img); - img->destroy(); - return ras; -} -#endif - // hack for reading native textures RwBool rwNativeTextureHackRead(RwStream *stream, RwTexture **tex, RwInt32 size) { *tex = Texture::streamReadNative(stream); #ifdef LIBRW -#ifdef PSP2 - (*tex)->raster = ConvertTexRaster((*tex)->raster); -#else (*tex)->raster = rw::Raster::convertTexToCurrentPlatform((*tex)->raster); -#endif #endif return *tex != nil; } diff --git a/src/renderer/ShadowCamera.cpp b/src/renderer/ShadowCamera.cpp index f69c234f..74ef095f 100644 --- a/src/renderer/ShadowCamera.cpp +++ b/src/renderer/ShadowCamera.cpp @@ -183,7 +183,7 @@ CShadowCamera::Update(RpClump *clump) RpGeometry *geometry; RwRGBA bgColor = { 255, 255, 255, 0 }; - + RwCameraClear(m_pCamera, &bgColor, rwCAMERACLEARZ | rwCAMERACLEARIMAGE); if ( RwCameraBeginUpdate(m_pCamera) ) @@ -219,10 +219,10 @@ CShadowCamera::Update(RpAtomic *atomic) RwRGBA bgColor = { 255, 255, 255, 0 }; RwCameraClear(m_pCamera, &bgColor, rwCAMERACLEARZ | rwCAMERACLEARIMAGE); - + if ( RwCameraBeginUpdate(m_pCamera) ) { - geometry = RpAtomicGetGeometry(atomic); + geometry = RpAtomicGetGeometry(atomic); ASSERT(geometry != nil); flags = RpGeometryGetFlags(geometry); diff --git a/src/rw/TexRead.cpp b/src/rw/TexRead.cpp index ee7f28d9..1818c159 100644 --- a/src/rw/TexRead.cpp +++ b/src/rw/TexRead.cpp @@ -185,8 +185,7 @@ GetGPUcaps(GPUcaps *caps) caps->subplatform = 0; caps->dxtSupport = 0; // TODO: more later -// librw-vita has no gl3Caps. -#if defined(RW_GL3) && !defined(PSP2) +#ifdef RW_GL3 caps->subplatform = rw::gl3::gl3Caps.gles; caps->dxtSupport = rw::gl3::gl3Caps.dxtSupported; #endif @@ -293,8 +292,8 @@ bool CanVideoCardDoDXT(void) { #ifdef LIBRW - // TODO #ifdef RW_OPENGL + // TODO: other GL targets still take the conversion path return false; #else return true; @@ -432,8 +431,7 @@ CreateTxdImageForVideoCard() return false; } -// librw-vita has no needToReadBackTextures - it always keeps texture data around. -#if defined(RW_GL3) && !defined(PSP2) +#ifdef RW_GL3 // so we can read back DXT with GLES // only works for textures that are not yet loaded // so let's hope that is the case for all diff --git a/src/skel/glfw/MoviePlayer.cpp b/src/skel/glfw/MoviePlayer.cpp index 0b0691df..2d7cda76 100644 --- a/src/skel/glfw/MoviePlayer.cpp +++ b/src/skel/glfw/MoviePlayer.cpp @@ -820,6 +820,7 @@ void movie_player_draw(void) { sceAvPlayerClose(movie_player); movie_player_audio_shutdown(); player_state = PLAYER_INACTIVE; + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); vglSwapBuffers(GL_FALSE); }