From c89056c23eb8338ce788f8d4e4a16d971acb6d69 Mon Sep 17 00:00:00 2001 From: olebeck <31539311+olebeck@users.noreply.github.com> Date: Fri, 4 Jul 2025 00:06:28 +0200 Subject: [PATCH] triple buffer textures because fences arent a thing on vita and making draw&cpu sync would be too slow --- .../legoomni/src/input/legoinputmanager.cpp | 3 +- miniwin/src/d3drm/backends/gxm/renderer.cpp | 65 ++++++++++++++----- miniwin/src/internal/d3drmrenderer_gxm.h | 14 +++- 3 files changed, 63 insertions(+), 19 deletions(-) diff --git a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp index ff15b122..3ee24be2 100644 --- a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp +++ b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp @@ -192,7 +192,8 @@ MxResult LegoInputManager::GetJoystickState(MxU32* p_joystickX, MxU32* p_joystic MxS16 xPos = SDL_GetJoystickAxis(m_joystick, 0); MxS16 yPos = SDL_GetJoystickAxis(m_joystick, 1); - MxU8 hatPos = SDL_GetJoystickHat(m_joystick, 0); + SDL_GetNumJoystickHats(m_joystick); + MxU8 hatPos = SDL_GetNumJoystickHats(m_joystick) > 0 ? SDL_GetJoystickHat(m_joystick, 0) : SDL_HAT_CENTERED; // normalize values acquired from joystick axes *p_joystickX = ((xPos + 32768) * 100) / 65535; diff --git a/miniwin/src/d3drm/backends/gxm/renderer.cpp b/miniwin/src/d3drm/backends/gxm/renderer.cpp index 1837b57c..b5c966f6 100644 --- a/miniwin/src/d3drm/backends/gxm/renderer.cpp +++ b/miniwin/src/d3drm/backends/gxm/renderer.cpp @@ -880,10 +880,15 @@ void GXMRenderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* textu [](IDirect3DRMObject* obj, void* arg) { auto* ctx = static_cast(arg); auto& cache = ctx->renderer->m_textures[ctx->textureId]; - void* textureData = sceGxmTextureGetData(&cache.gxmTexture); - gxm->free(textureData); + for(int i = 0; i < cache.bufferCount; i++) { + if(cache.notifications[i]) { + sceGxmNotificationWait(cache.notifications[i]); + } + void* textureData = sceGxmTextureGetData(&cache.gxmTexture[i]); + gxm->free(textureData); + memset(&cache.gxmTexture[i], 0, sizeof(SceGxmTexture)); + } cache.texture = nullptr; - memset(&cache.gxmTexture, 0, sizeof(cache.gxmTexture)); delete ctx; }, ctx @@ -1008,8 +1013,23 @@ Uint32 GXMRenderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) auto& tex = m_textures[i]; if (tex.texture == texture) { if (tex.version != texture->m_version) { - void* textureData = sceGxmTextureGetData(&tex.gxmTexture); - copySurfaceToGxm(surface, (uint8_t*) textureData, textureStride, textureSize); + if(tex.bufferCount != GXM_TEXTURE_BUFFER_COUNT) { + for(int i = 1; i < GXM_TEXTURE_BUFFER_COUNT; i++) { + tex.gxmTexture[i] = tex.gxmTexture[0]; + uint8_t* textureData = (uint8_t*)gxm->alloc(textureSize, textureAlignment); + sceGxmTextureSetData(&tex.gxmTexture[i], textureData); + } + tex.bufferCount = GXM_TEXTURE_BUFFER_COUNT; + } + if(tex.bufferCount > 1) { + tex.currentIndex = (tex.currentIndex + 1) % GXM_TEXTURE_BUFFER_COUNT; + } + if(tex.notifications[tex.currentIndex]) { + sceGxmNotificationWait(tex.notifications[tex.currentIndex]); + } + tex.notifications[tex.currentIndex] = &this->fragmentNotifications[this->currentFragmentBufferIndex]; + uint8_t* textureData = (uint8_t*)sceGxmTextureGetData(&tex.gxmTexture[tex.currentIndex]); + copySurfaceToGxm(surface, textureData, textureStride, textureSize); tex.version = texture->m_version; } return i; @@ -1043,15 +1063,27 @@ Uint32 GXMRenderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) for (Uint32 i = 0; i < m_textures.size(); ++i) { auto& tex = m_textures[i]; if (!tex.texture) { + memset(&tex, 0, sizeof(tex)); tex.texture = texture; tex.version = texture->m_version; - tex.gxmTexture = gxmTexture; + tex.bufferCount = 1; + tex.currentIndex = 0; + tex.gxmTexture[0] = gxmTexture; + tex.notifications[0] = &this->fragmentNotifications[this->currentFragmentBufferIndex]; AddTextureDestroyCallback(i, texture); return i; } } - m_textures.push_back({texture, texture->m_version, gxmTexture}); + GXMTextureCacheEntry tex; + memset(&tex, 0, sizeof(tex)); + tex.texture = texture; + tex.version = texture->m_version; + tex.bufferCount = 1; + tex.currentIndex = 0; + tex.gxmTexture[0] = gxmTexture; + tex.notifications[0] = &this->fragmentNotifications[this->currentFragmentBufferIndex]; + m_textures.push_back(tex); Uint32 textureId = (Uint32) (m_textures.size() - 1); AddTextureDestroyCallback(textureId, texture); return textureId; @@ -1474,7 +1506,7 @@ void GXMRenderer::SubmitDraw( if (textured) { auto& texture = m_textures[appearance.textureId]; - sceGxmSetFragmentTexture(gxm->context, 0, &texture.gxmTexture); + this->UseTexture(texture); } #ifdef GXM_PRECOMPUTE @@ -1575,11 +1607,10 @@ void GXMRenderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const S SET_UNIFORM(vertUniforms, this->uNormalMatrix, normal); // float3x3 SET_UNIFORM(vertUniforms, this->uProjectionMatrix, projection); // float4x4 - const GXMTextureCacheEntry& texture = m_textures[textureId]; - sceGxmSetFragmentTexture(gxm->context, 0, &texture.gxmTexture); - - float texW = sceGxmTextureGetWidth(&texture.gxmTexture); - float texH = sceGxmTextureGetHeight(&texture.gxmTexture); + GXMTextureCacheEntry& texture = m_textures[textureId]; + const SceGxmTexture* gxmTexture = this->UseTexture(texture); + float texW = sceGxmTextureGetWidth(gxmTexture); + float texH = sceGxmTextureGetHeight(gxmTexture); float u1 = static_cast(srcRect.x) / texW; float v1 = static_cast(srcRect.y) / texH; @@ -1613,11 +1644,11 @@ void GXMRenderer::Download(SDL_Surface* target) static_cast(target->h * m_viewportTransform.scale), }; SDL_Surface* src = SDL_CreateSurfaceFrom( - this->m_width, - this->m_height, - SDL_PIXELFORMAT_RGBA32, + VITA_GXM_SCREEN_WIDTH, + VITA_GXM_SCREEN_HEIGHT, + SDL_PIXELFORMAT_RGBA8888, gxm->displayBuffers[gxm->frontBufferIndex], - VITA_GXM_SCREEN_STRIDE + VITA_GXM_SCREEN_STRIDE*4 ); SDL_BlitSurfaceScaled(src, &srcRect, target, nullptr, SDL_SCALEMODE_NEAREST); SDL_DestroySurface(src); diff --git a/miniwin/src/internal/d3drmrenderer_gxm.h b/miniwin/src/internal/d3drmrenderer_gxm.h index 80abef39..928cab28 100644 --- a/miniwin/src/internal/d3drmrenderer_gxm.h +++ b/miniwin/src/internal/d3drmrenderer_gxm.h @@ -12,17 +12,23 @@ #include #include +#include "gxm_context.h" + DEFINE_GUID(GXM_GUID, 0x682656F3, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x58, 0x4D); #define GXM_VERTEX_BUFFER_COUNT 2 #define GXM_FRAGMENT_BUFFER_COUNT 3 +#define GXM_TEXTURE_BUFFER_COUNT 2 //#define GXM_PRECOMPUTE struct GXMTextureCacheEntry { IDirect3DRMTexture* texture; Uint32 version; - SceGxmTexture gxmTexture; + int bufferCount; + int currentIndex; + SceGxmTexture gxmTexture[GXM_TEXTURE_BUFFER_COUNT]; + SceGxmNotification* notifications[GXM_TEXTURE_BUFFER_COUNT]; }; struct GXMMeshCacheEntry { @@ -108,6 +114,12 @@ class GXMRenderer : public Direct3DRMRenderer { GXMMeshCacheEntry GXMUploadMesh(const MeshGroup& meshGroup); void StartScene(); + inline const SceGxmTexture* UseTexture(GXMTextureCacheEntry& texture) { + texture.notifications[texture.currentIndex] = &this->fragmentNotifications[this->currentFragmentBufferIndex]; + const SceGxmTexture* gxmTexture = &texture.gxmTexture[texture.currentIndex]; + sceGxmSetFragmentTexture(gxm->context, 0, gxmTexture); + return gxmTexture; + } inline Vertex* QuadVerticesBuffer() { Vertex* verts = &this->quadVertices[this->currentVertexBufferIndex][this->quadsUsed*4];