SDL: Vita: Use preallocated memory pool for textures

From 95ed83137f373bfde4f3d4aa256498e2b15173fa Mon Sep 17 00:00:00 2001
From: Ivan Epifanov <[EMAIL REDACTED]>
Date: Fri, 25 Mar 2022 15:22:10 +0300
Subject: [PATCH] Vita: Use preallocated memory pool for textures

---
 src/render/vitagxm/SDL_render_vita_gxm.c      |  2 +-
 .../vitagxm/SDL_render_vita_gxm_memory.c      | 76 +++++++++++++--
 .../vitagxm/SDL_render_vita_gxm_memory.h      | 16 +--
 .../vitagxm/SDL_render_vita_gxm_tools.c       | 97 ++++++++++---------
 .../vitagxm/SDL_render_vita_gxm_tools.h       |  2 +-
 .../vitagxm/SDL_render_vita_gxm_types.h       |  4 +
 6 files changed, 137 insertions(+), 60 deletions(-)

diff --git a/src/render/vitagxm/SDL_render_vita_gxm.c b/src/render/vitagxm/SDL_render_vita_gxm.c
index 0dac8eaa3ff..98b03e62941 100644
--- a/src/render/vitagxm/SDL_render_vita_gxm.c
+++ b/src/render/vitagxm/SDL_render_vita_gxm.c
@@ -1246,7 +1246,7 @@ VITA_GXM_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
 
     sceGxmFinish(data->gxm_context);
 
-    free_gxm_texture(vita_texture->tex);
+    free_gxm_texture(data, vita_texture->tex);
 
     SDL_free(vita_texture);
 
diff --git a/src/render/vitagxm/SDL_render_vita_gxm_memory.c b/src/render/vitagxm/SDL_render_vita_gxm_memory.c
index d3322730ada..271a68c267f 100644
--- a/src/render/vitagxm/SDL_render_vita_gxm_memory.c
+++ b/src/render/vitagxm/SDL_render_vita_gxm_memory.c
@@ -26,7 +26,7 @@
 #include "SDL_render_vita_gxm_memory.h"
 
 void *
-mem_gpu_alloc(SceKernelMemBlockType type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid)
+vita_mem_alloc(SceKernelMemBlockType type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid)
 {
     void *mem;
 
@@ -51,7 +51,7 @@ mem_gpu_alloc(SceKernelMemBlockType type, unsigned int size, unsigned int alignm
 }
 
 void
-mem_gpu_free(SceUID uid)
+vita_mem_free(SceUID uid)
 {
     void *mem = NULL;
     if (sceKernelGetMemBlockBase(uid, &mem) < 0)
@@ -61,7 +61,71 @@ mem_gpu_free(SceUID uid)
 }
 
 void *
-mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
+vita_gpu_mem_alloc(VITA_GXM_RenderData *data, unsigned int size)
+{
+    void *mem;
+
+    if (data->texturePool == NULL) {
+        int poolsize;
+        int ret;
+        SceKernelFreeMemorySizeInfo info;
+        info.size = sizeof(SceKernelFreeMemorySizeInfo);
+        sceKernelGetFreeMemorySize(&info);
+
+        poolsize = ALIGN(info.size_cdram, 256*1024);
+        if (poolsize > info.size_cdram) {
+            poolsize = ALIGN(info.size_cdram - 256*1024, 256*1024);
+        }
+        data->texturePoolUID = sceKernelAllocMemBlock("gpu_texture_pool", SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, poolsize, NULL);
+        if (data->texturePoolUID < 0) {
+            return NULL;
+        }
+
+        ret = sceKernelGetMemBlockBase(data->texturePoolUID, &mem);
+        if ( ret < 0)
+        {
+            return NULL;
+        }
+        data->texturePool = sceClibMspaceCreate(mem, poolsize);
+
+        if (data->texturePool == NULL) {
+            return NULL;
+        }
+        ret = sceGxmMapMemory(mem, poolsize, SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE);
+        if (ret < 0)
+        {
+            return NULL;
+        }
+    }
+    return sceClibMspaceMemalign(data->texturePool, SCE_GXM_TEXTURE_ALIGNMENT, size);
+}
+
+void
+vita_gpu_mem_free(VITA_GXM_RenderData *data, void* ptr)
+{
+    if (data->texturePool != NULL)
+    {
+        sceClibMspaceFree(data->texturePool, ptr);
+    }
+}
+
+void
+vita_gpu_mem_destroy(VITA_GXM_RenderData *data)
+{
+    void *mem = NULL;
+    if (data->texturePool != NULL)
+    {
+        sceClibMspaceDestroy(data->texturePool);
+        data->texturePool = NULL;
+        if (sceKernelGetMemBlockBase(data->texturePoolUID, &mem) < 0)
+            return;
+        sceGxmUnmapMemory(mem);
+        sceKernelFreeMemBlock(data->texturePoolUID);
+    }
+}
+
+void *
+vita_mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
 {
     void *mem = NULL;
 
@@ -77,7 +141,7 @@ mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
 }
 
 void
-mem_vertex_usse_free(SceUID uid)
+vita_mem_vertex_usse_free(SceUID uid)
 {
     void *mem = NULL;
     if (sceKernelGetMemBlockBase(uid, &mem) < 0)
@@ -87,7 +151,7 @@ mem_vertex_usse_free(SceUID uid)
 }
 
 void *
-mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
+vita_mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
 {
     void *mem = NULL;
 
@@ -103,7 +167,7 @@ mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offse
 }
 
 void
-mem_fragment_usse_free(SceUID uid)
+vita_mem_fragment_usse_free(SceUID uid)
 {
     void *mem = NULL;
     if (sceKernelGetMemBlockBase(uid, &mem) < 0)
diff --git a/src/render/vitagxm/SDL_render_vita_gxm_memory.h b/src/render/vitagxm/SDL_render_vita_gxm_memory.h
index 51bc8a80a19..d7116654b3b 100644
--- a/src/render/vitagxm/SDL_render_vita_gxm_memory.h
+++ b/src/render/vitagxm/SDL_render_vita_gxm_memory.h
@@ -25,15 +25,19 @@
 #include <psp2/gxm.h>
 #include <psp2/types.h>
 #include <psp2/kernel/sysmem.h>
+#include "SDL_render_vita_gxm_types.h"
 
 #define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
 
-void *mem_gpu_alloc(SceKernelMemBlockType type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid);
-void mem_gpu_free(SceUID uid);
-void *mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset);
-void mem_vertex_usse_free(SceUID uid);
-void *mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset);
-void mem_fragment_usse_free(SceUID uid);
+void *vita_mem_alloc(SceKernelMemBlockType type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid);
+void vita_mem_free(SceUID uid);
+void *vita_gpu_mem_alloc(VITA_GXM_RenderData *data, unsigned int size);
+void vita_gpu_mem_free(VITA_GXM_RenderData *data, void* ptr);
+void vita_gpu_mem_destroy(VITA_GXM_RenderData *data);
+void *vita_mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset);
+void vita_mem_vertex_usse_free(SceUID uid);
+void *vita_mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset);
+void vita_mem_fragment_usse_free(SceUID uid);
 
 #endif /* SDL_RENDER_VITA_GXM_MEMORY_H */
 
diff --git a/src/render/vitagxm/SDL_render_vita_gxm_tools.c b/src/render/vitagxm/SDL_render_vita_gxm_tools.c
index 0ecae38394c..035e8a63c4e 100644
--- a/src/render/vitagxm/SDL_render_vita_gxm_tools.c
+++ b/src/render/vitagxm/SDL_render_vita_gxm_tools.c
@@ -416,28 +416,28 @@ gxm_init(SDL_Renderer *renderer)
     }
 
     // allocate ring buffer memory using default sizes
-    vdmRingBuffer = mem_gpu_alloc(
+    vdmRingBuffer = vita_mem_alloc(
         SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
         SCE_GXM_DEFAULT_VDM_RING_BUFFER_SIZE,
         4,
         SCE_GXM_MEMORY_ATTRIB_READ,
         &data->vdmRingBufferUid);
 
-    vertexRingBuffer = mem_gpu_alloc(
+    vertexRingBuffer = vita_mem_alloc(
         SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
         SCE_GXM_DEFAULT_VERTEX_RING_BUFFER_SIZE,
         4,
         SCE_GXM_MEMORY_ATTRIB_READ,
         &data->vertexRingBufferUid);
 
-    fragmentRingBuffer = mem_gpu_alloc(
+    fragmentRingBuffer = vita_mem_alloc(
         SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
         SCE_GXM_DEFAULT_FRAGMENT_RING_BUFFER_SIZE,
         4,
         SCE_GXM_MEMORY_ATTRIB_READ,
         &data->fragmentRingBufferUid);
 
-    fragmentUsseRingBuffer = mem_fragment_usse_alloc(
+    fragmentUsseRingBuffer = vita_mem_fragment_usse_alloc(
         SCE_GXM_DEFAULT_FRAGMENT_USSE_RING_BUFFER_SIZE,
         &data->fragmentUsseRingBufferUid,
         &fragmentUsseRingBufferOffset);
@@ -482,7 +482,7 @@ gxm_init(SDL_Renderer *renderer)
     for (i = 0; i < VITA_GXM_BUFFERS; i++) {
 
         // allocate memory for display
-        data->displayBufferData[i] = mem_gpu_alloc(
+        data->displayBufferData[i] = vita_mem_alloc(
             SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
             4 * VITA_GXM_SCREEN_STRIDE * VITA_GXM_SCREEN_HEIGHT,
             SCE_GXM_COLOR_SURFACE_ALIGNMENT,
@@ -527,7 +527,7 @@ gxm_init(SDL_Renderer *renderer)
 
 
     // allocate the depth buffer
-    data->depthBufferData = mem_gpu_alloc(
+    data->depthBufferData = vita_mem_alloc(
         SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
         4 * sampleCount,
         SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT,
@@ -535,7 +535,7 @@ gxm_init(SDL_Renderer *renderer)
         &data->depthBufferUid);
 
     // allocate the stencil buffer
-    data->stencilBufferData = mem_gpu_alloc(
+    data->stencilBufferData = vita_mem_alloc(
         SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
         4 * sampleCount,
         SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT,
@@ -567,19 +567,19 @@ gxm_init(SDL_Renderer *renderer)
 
 
     // allocate memory for buffers and USSE code
-    patcherBuffer = mem_gpu_alloc(
+    patcherBuffer = vita_mem_alloc(
         SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
         patcherBufferSize,
         4,
         SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
         &data->patcherBufferUid);
 
-    patcherVertexUsse = mem_vertex_usse_alloc(
+    patcherVertexUsse = vita_mem_vertex_usse_alloc(
         patcherVertexUsseSize,
         &data->patcherVertexUsseUid,
         &patcherVertexUsseOffset);
 
-    patcherFragmentUsse = mem_fragment_usse_alloc(
+    patcherFragmentUsse = vita_mem_fragment_usse_alloc(
         patcherFragmentUsseSize,
         &data->patcherFragmentUsseUid,
         &patcherFragmentUsseOffset);
@@ -730,7 +730,7 @@ gxm_init(SDL_Renderer *renderer)
         }
 
         // create the clear triangle vertex/index data
-        data->clearVertices = (clear_vertex *)mem_gpu_alloc(
+        data->clearVertices = (clear_vertex *)vita_mem_alloc(
             SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
             3*sizeof(clear_vertex),
             4,
@@ -742,7 +742,7 @@ gxm_init(SDL_Renderer *renderer)
     // Allocate a 64k * 2 bytes = 128 KiB buffer and store all possible
     // 16-bit indices in linear ascending order, so we can use this for
     // all drawing operations where we don't want to use indexing.
-    data->linearIndices = (uint16_t *)mem_gpu_alloc(
+    data->linearIndices = (uint16_t *)vita_mem_alloc(
         SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
         UINT16_MAX*sizeof(uint16_t),
         sizeof(uint16_t),
@@ -873,7 +873,7 @@ gxm_init(SDL_Renderer *renderer)
     data->textureWvpParam = (SceGxmProgramParameter *)sceGxmProgramFindParameterByName(textureVertexProgramGxp, "wvp");
 
     // Allocate memory for the memory pool
-    data->pool_addr[0] = mem_gpu_alloc(
+    data->pool_addr[0] = vita_mem_alloc(
         SCE_KERNEL_MEMBLOCK_TYPE_USER_RW,
         VITA_GXM_POOL_SIZE,
         sizeof(void *),
@@ -881,7 +881,7 @@ gxm_init(SDL_Renderer *renderer)
         &data->poolUid[0]
     );
 
-    data->pool_addr[1] = mem_gpu_alloc(
+    data->pool_addr[1] = vita_mem_alloc(
         SCE_KERNEL_MEMBLOCK_TYPE_USER_RW,
         VITA_GXM_POOL_SIZE,
         sizeof(void *),
@@ -920,28 +920,28 @@ void gxm_finish(SDL_Renderer *renderer)
     free_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_mod);
     free_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_mul);
 
-    mem_gpu_free(data->linearIndicesUid);
-    mem_gpu_free(data->clearVerticesUid);
+    vita_mem_free(data->linearIndicesUid);
+    vita_mem_free(data->clearVerticesUid);
 
     // wait until display queue is finished before deallocating display buffers
     sceGxmDisplayQueueFinish();
 
     // clean up display queue
-    mem_gpu_free(data->depthBufferUid);
+    vita_mem_free(data->depthBufferUid);
 
     for (size_t i = 0; i < VITA_GXM_BUFFERS; i++)
     {
         // clear the buffer then deallocate
         SDL_memset(data->displayBufferData[i], 0, VITA_GXM_SCREEN_HEIGHT * VITA_GXM_SCREEN_STRIDE * 4);
-        mem_gpu_free(data->displayBufferUid[i]);
+        vita_mem_free(data->displayBufferUid[i]);
 
         // destroy the sync object
         sceGxmSyncObjectDestroy(data->displayBufferSync[i]);
     }
 
     // Free the depth and stencil buffer
-    mem_gpu_free(data->depthBufferUid);
-    mem_gpu_free(data->stencilBufferUid);
+    vita_mem_free(data->depthBufferUid);
+    vita_mem_free(data->stencilBufferUid);
 
     // unregister programs and destroy shader patcher
     sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->clearFragmentProgramId);
@@ -952,23 +952,24 @@ void gxm_finish(SDL_Renderer *renderer)
     sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->textureVertexProgramId);
 
     sceGxmShaderPatcherDestroy(data->shaderPatcher);
-    mem_fragment_usse_free(data->patcherFragmentUsseUid);
-    mem_vertex_usse_free(data->patcherVertexUsseUid);
-    mem_gpu_free(data->patcherBufferUid);
+    vita_mem_fragment_usse_free(data->patcherFragmentUsseUid);
+    vita_mem_vertex_usse_free(data->patcherVertexUsseUid);
+    vita_mem_free(data->patcherBufferUid);
 
     // destroy the render target
     sceGxmDestroyRenderTarget(data->renderTarget);
 
     // destroy the gxm context
     sceGxmDestroyContext(data->gxm_context);
-    mem_fragment_usse_free(data->fragmentUsseRingBufferUid);
-    mem_gpu_free(data->fragmentRingBufferUid);
-    mem_gpu_free(data->vertexRingBufferUid);
-    mem_gpu_free(data->vdmRingBufferUid);
+    vita_mem_fragment_usse_free(data->fragmentUsseRingBufferUid);
+    vita_mem_free(data->fragmentRingBufferUid);
+    vita_mem_free(data->vertexRingBufferUid);
+    vita_mem_free(data->vdmRingBufferUid);
     SDL_free(data->contextParams.hostMem);
 
-    mem_gpu_free(data->poolUid[0]);
-    mem_gpu_free(data->poolUid[1]);
+    vita_mem_free(data->poolUid[0]);
+    vita_mem_free(data->poolUid[1]);
+    vita_gpu_mem_destroy(data);
 
     // terminate libgxm
     sceGxmTerminate();
@@ -977,16 +978,20 @@ void gxm_finish(SDL_Renderer *renderer)
 // textures
 
 void
-free_gxm_texture(gxm_texture *texture)
+free_gxm_texture(VITA_GXM_RenderData *data, gxm_texture *texture)
 {
     if (texture) {
         if (texture->gxm_rendertarget) {
             sceGxmDestroyRenderTarget(texture->gxm_rendertarget);
         }
         if (texture->depth_UID) {
-            mem_gpu_free(texture->depth_UID);
+            vita_mem_free(texture->depth_UID);
+        }
+        if (texture->cdram) {
+            vita_gpu_mem_free(data, sceGxmTextureGetData(&texture->gxm_tex));
+        } else {
+            vita_mem_free(texture->data_UID);
         }
-        mem_gpu_free(texture->data_UID);
         SDL_free(texture);
     }
 }
@@ -1033,24 +1038,24 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
     *return_pitch = aligned_w * tex_format_to_bytespp(format);
 
     /* Allocate a GPU buffer for the texture */
-    texture_data = mem_gpu_alloc(
-        SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
-        tex_size,
-        SCE_GXM_TEXTURE_ALIGNMENT,
-        SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
-        &texture->data_UID
+    texture_data = vita_gpu_mem_alloc(
+        data,
+        tex_size
     );
 
     /* Try SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE in case we're out of VRAM */
     if (!texture_data) {
         SDL_LogWarn(SDL_LOG_CATEGORY_RENDER, "CDRAM texture allocation failed\n");
-        texture_data = mem_gpu_alloc(
+        texture_data = vita_mem_alloc(
             SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
             tex_size,
             SCE_GXM_TEXTURE_ALIGNMENT,
             SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
             &texture->data_UID
         );
+        texture->cdram = 0;
+    } else {
+        texture->cdram = 1;
     }
 
     if (!texture_data) {
@@ -1064,7 +1069,7 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
     /* Create the gxm texture */
     ret = sceGxmTextureInitLinear( &texture->gxm_tex, texture_data, format, texture_w, h, 0);
     if (ret < 0) {
-      free_gxm_texture(texture);
+      free_gxm_texture(data, texture);
       SDL_LogError(SDL_LOG_CATEGORY_RENDER, "texture init failed: %x\n", ret);
       return NULL;
     }
@@ -1090,13 +1095,13 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
         );
 
         if (err < 0) {
-            free_gxm_texture(texture);
+            free_gxm_texture(data, texture);
             SDL_LogError(SDL_LOG_CATEGORY_RENDER, "color surface init failed: %x\n", err);
             return NULL;
         }
 
         // allocate it
-        depthBufferData = mem_gpu_alloc(
+        depthBufferData = vita_mem_alloc(
             SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
             4*sampleCount,
             SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT,
@@ -1113,7 +1118,7 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
             NULL);
 
         if (err < 0) {
-            free_gxm_texture(texture);
+            free_gxm_texture(data, texture);
             SDL_LogError(SDL_LOG_CATEGORY_RENDER, "depth stencil init failed: %x\n", err);
             return NULL;
         }
@@ -1138,7 +1143,7 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
             texture->gxm_rendertarget = tgt;
 
             if (err < 0) {
-                free_gxm_texture(texture);
+                free_gxm_texture(data, texture);
                 SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create render target failed: %x\n", err);
                 return NULL;
             }
@@ -1188,7 +1193,7 @@ void gxm_init_for_common_dialog(void)
     for (int i = 0; i < VITA_GXM_BUFFERS; i += 1)
     {
         buffer_for_common_dialog[i].displayData.wait_vblank = SDL_TRUE;
-        buffer_for_common_dialog[i].displayData.address = mem_gpu_alloc(
+        buffer_for_common_dialog[i].displayData.address = vita_mem_alloc(
             SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
             4 * VITA_GXM_SCREEN_STRIDE * VITA_GXM_SCREEN_HEIGHT,
             SCE_GXM_COLOR_SURFACE_ALIGNMENT,
@@ -1236,7 +1241,7 @@ void gxm_term_for_common_dialog(void)
     sceGxmDisplayQueueFinish();
     for (int i = 0; i < VITA_GXM_BUFFERS; i += 1)
     {
-        mem_gpu_free(buffer_for_common_dialog[i].uid);
+        vita_mem_free(buffer_for_common_dialog[i].uid);
         sceGxmSyncObjectDestroy(buffer_for_common_dialog[i].sync);
     }
 }
diff --git a/src/render/vitagxm/SDL_render_vita_gxm_tools.h b/src/render/vitagxm/SDL_render_vita_gxm_tools.h
index 8e9caeb2102..67659889dcf 100644
--- a/src/render/vitagxm/SDL_render_vita_gxm_tools.h
+++ b/src/render/vitagxm/SDL_render_vita_gxm_tools.h
@@ -49,7 +49,7 @@ int gxm_init(SDL_Renderer *renderer);
 void gxm_finish(SDL_Renderer *renderer);
 
 gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget, unsigned int *return_w, unsigned int *return_h, unsigned int *return_pitch, float *return_wscale);
-void free_gxm_texture(gxm_texture *texture);
+void free_gxm_texture(VITA_GXM_RenderData *data, gxm_texture *texture);
 
 void gxm_texture_set_filters(gxm_texture *texture, SceGxmTextureFilter min_filter, SceGxmTextureFilter mag_filter);
 SceGxmTextureFormat gxm_texture_get_format(const gxm_texture *texture);
diff --git a/src/render/vitagxm/SDL_render_vita_gxm_types.h b/src/render/vitagxm/SDL_render_vita_gxm_types.h
index 2bf8d358505..c5cbf5898b6 100644
--- a/src/render/vitagxm/SDL_render_vita_gxm_types.h
+++ b/src/render/vitagxm/SDL_render_vita_gxm_types.h
@@ -33,6 +33,7 @@
 #include <psp2/gxm.h>
 #include <psp2/types.h>
 #include <psp2/kernel/sysmem.h>
+#include <psp2/kernel/clib.h>
 
 #include <string.h>
 
@@ -79,6 +80,7 @@ typedef struct gxm_texture {
     SceGxmColorSurface gxm_colorsurface;
     SceGxmDepthStencilSurface gxm_depthstencil;
     SceUID depth_UID;
+    SDL_bool cdram;
 } gxm_texture;
 
 typedef struct fragment_programs {
@@ -186,6 +188,8 @@ typedef struct
     blend_fragment_programs blendFragmentPrograms;
 
     gxm_drawstate_cache drawstate;
+    SceClibMspace texturePool;
+    SceUID texturePoolUID;
 } VITA_GXM_RenderData;
 
 typedef struct