From 0d8c1054ebe43e373fc6f08dec7e34148e1b6b48 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 19 Aug 2023 16:21:20 +1000 Subject: [PATCH] Vita: Now clearing works at least --- src/Graphics_PSVita.c | 310 +++++++++++++++++++++++++++++++++++------- 1 file changed, 262 insertions(+), 48 deletions(-) diff --git a/src/Graphics_PSVita.c b/src/Graphics_PSVita.c index 4e9ac3a96..0ff841e0b 100644 --- a/src/Graphics_PSVita.c +++ b/src/Graphics_PSVita.c @@ -7,12 +7,13 @@ #include /* Current format and size of vertices */ static int gfx_stride, gfx_format = -1; +static int frontBufferIndex, backBufferIndex; #define DISPLAY_WIDTH 960 #define DISPLAY_HEIGHT 544 #define DISPLAY_STRIDE 1024 -#define NUM_DISPLAY_BUFFERS 2 +#define NUM_DISPLAY_BUFFERS 3 // TODO: or just 2? #define MAX_PENDING_SWAPS (NUM_DISPLAY_BUFFERS - 1) static SceGxmContext* gxm_context; @@ -37,6 +38,33 @@ static SceUID gxm_depth_stencil_surface_uid; static void* gxm_depth_stencil_surface_addr; static SceGxmDepthStencilSurface gxm_depth_stencil_surface; +static SceGxmShaderPatcher *gxm_shader_patcher; +static const int shader_patcher_buffer_size = 64 * 1024;; +static SceUID gxm_shader_patcher_buffer_uid; +static void* gxm_shader_patcher_buffer_addr; + +static const int shader_patcher_vertex_usse_size = 64 * 1024; +static SceUID gxm_shader_patcher_vertex_usse_uid; +static void* gxm_shader_patcher_vertex_usse_addr; +static unsigned int shader_patcher_vertex_usse_offset; + +static const int shader_patcher_fragment_usse_size = 64 * 1024; +static SceUID gxm_shader_patcher_fragment_usse_uid; +static void* gxm_shader_patcher_fragment_usse_addr; +static unsigned int shader_patcher_fragment_usse_offset; + +static SceGxmShaderPatcherId gxm_clear_vertex_program_id; +static SceGxmShaderPatcherId gxm_clear_fragment_program_id; +static const SceGxmProgramParameter* gxm_clear_vertex_program_position_param; +static const SceGxmProgramParameter* gxm_clear_fragment_program_clear_color_param; +static SceGxmVertexProgram* gxm_clear_vertex_program_patched; +static SceGxmFragmentProgram* gxm_clear_fragment_program_patched; + +#include "../misc/vita/clear_fs.h" +#include "../misc/vita/clear_vs.h" +static SceGxmProgram* gxm_program_clear_vs = (SceGxmProgram *)&clear_vs; +static SceGxmProgram* gxm_program_clear_fs = (SceGxmProgram *)&clear_fs; + /*########################################################################################################################* *---------------------------------------------------------Memory----------------------------------------------------------* *#########################################################################################################################*/ @@ -107,30 +135,51 @@ void* AllocGPUFragmentUSSE(size_t size, SceUID* ret_uid, unsigned int* ret_usse_ return addr; } +static void FreeGPUMemory(SceUID uid) { + void *addr; + + if (sceKernelGetMemBlockBase(uid, &addr) < 0) + return; + + sceGxmUnmapMemory(addr); + sceKernelFreeMemBlock(uid); +} + +static void* AllocShaderPatcherMem(void* user_data, unsigned int size) { + return Mem_TryAlloc(1, size); +} + +static void FreeShaderPatcherMem(void* user_data, void* mem) { + Mem_Free(mem); +} + /*########################################################################################################################* *-----------------------------------------------------Initialisation------------------------------------------------------* *#########################################################################################################################*/ -static void DisplayQueueCallback(const void *callback_data) { - SceDisplayFrameBuf fb = { 0 }; - void* addr = *((void **)callback_data); +struct DQCallbackData { void* addr; }; + +static void DQCallback(const void *callback_data) { + SceDisplayFrameBuf fb = { 0 }; fb.size = sizeof(SceDisplayFrameBuf); - fb.base = addr; + fb.base = ((struct DQCallbackData*)callback_data)->addr; fb.pitch = DISPLAY_STRIDE; fb.pixelformat = SCE_DISPLAY_PIXELFORMAT_A8B8G8R8; fb.width = DISPLAY_WIDTH; fb.height = DISPLAY_HEIGHT; sceDisplaySetFrameBuf(&fb, SCE_DISPLAY_SETBUF_NEXTFRAME); + + if (gfx_vsync) sceDisplayWaitVblankStart(); } static void InitGXM(void) { SceGxmInitializeParams params = { 0 }; params.displayQueueMaxPendingCount = MAX_PENDING_SWAPS; - params.displayQueueCallback = DisplayQueueCallback; - params.displayQueueCallbackDataSize = sizeof(void*); + params.displayQueueCallback = DQCallback; + params.displayQueueCallbackDataSize = sizeof(struct DQCallbackData); params.parameterBufferSize = SCE_GXM_DEFAULT_PARAMETER_BUFFER_SIZE; sceGxmInitialize(¶ms); @@ -156,7 +205,7 @@ static void AllocRingBuffers(void) { static void AllocGXMContext(void) { SceGxmContextParams params = { 0 }; - params.hostMem = Mem_TryAlloc(SCE_GXM_MINIMUM_CONTEXT_HOST_MEM_SIZE, 1); + params.hostMem = Mem_TryAlloc(1, SCE_GXM_MINIMUM_CONTEXT_HOST_MEM_SIZE); params.hostMemSize = SCE_GXM_MINIMUM_CONTEXT_HOST_MEM_SIZE; params.vdmRingBufferMem = vdm_ring_buffer_addr; @@ -217,6 +266,81 @@ static void AllocDepthBuffer(void) { width, gxm_depth_stencil_surface_addr, NULL); } +static void AllocShaderPatcherMemory(void) { + gxm_shader_patcher_buffer_addr = AllocGPUMemory(shader_patcher_buffer_size, + SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, SCE_GXM_MEMORY_ATTRIB_READ, + &gxm_shader_patcher_buffer_uid); + + gxm_shader_patcher_vertex_usse_addr = AllocGPUVertexUSSE( + shader_patcher_vertex_usse_size, &gxm_shader_patcher_vertex_usse_uid, + &shader_patcher_vertex_usse_offset); + + gxm_shader_patcher_fragment_usse_addr = AllocGPUFragmentUSSE( + shader_patcher_fragment_usse_size, &gxm_shader_patcher_fragment_usse_uid, + &shader_patcher_fragment_usse_offset); +} + +static void AllocShaderPatcher(void) { + SceGxmShaderPatcherParams params = { 0 }; + params.hostAllocCallback = AllocShaderPatcherMem; + params.hostFreeCallback = FreeShaderPatcherMem; + + params.bufferMem = gxm_shader_patcher_buffer_addr; + params.bufferMemSize = shader_patcher_buffer_size; + + params.vertexUsseMem = gxm_shader_patcher_vertex_usse_addr; + params.vertexUsseMemSize = shader_patcher_vertex_usse_size; + params.vertexUsseOffset = shader_patcher_vertex_usse_offset; + + params.fragmentUsseMem = gxm_shader_patcher_fragment_usse_addr; + params.fragmentUsseMemSize = shader_patcher_fragment_usse_size; + params.fragmentUsseOffset = shader_patcher_fragment_usse_offset; + + sceGxmShaderPatcherCreate(¶ms, &gxm_shader_patcher); +} + +struct clear_vertex { + float x, y, z; +}; + +static void AllocClearShader(void) { + sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_clear_vs, + &gxm_clear_vertex_program_id); + sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_clear_fs, + &gxm_clear_fragment_program_id); + + const SceGxmProgram *clear_vertex_program = + sceGxmShaderPatcherGetProgramFromId(gxm_clear_vertex_program_id); + const SceGxmProgram *clear_fragment_program = + sceGxmShaderPatcherGetProgramFromId(gxm_clear_fragment_program_id); + + gxm_clear_vertex_program_position_param = sceGxmProgramFindParameterByName( + clear_vertex_program, "position"); + + gxm_clear_fragment_program_clear_color_param = sceGxmProgramFindParameterByName( + clear_fragment_program, "clearColor"); + + SceGxmVertexAttribute clear_vertex_attribute; + SceGxmVertexStream clear_vertex_stream; + clear_vertex_attribute.streamIndex = 0; + clear_vertex_attribute.offset = 0; + clear_vertex_attribute.format = SCE_GXM_ATTRIBUTE_FORMAT_F32; + clear_vertex_attribute.componentCount = 2; + clear_vertex_attribute.regIndex = sceGxmProgramParameterGetResourceIndex( + gxm_clear_vertex_program_position_param); + clear_vertex_stream.stride = sizeof(struct clear_vertex); + clear_vertex_stream.indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; + + sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher, + gxm_clear_vertex_program_id, &clear_vertex_attribute, + 1, &clear_vertex_stream, 1, &gxm_clear_vertex_program_patched); + + sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher, + gxm_clear_fragment_program_id, SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, + SCE_GXM_MULTISAMPLE_NONE, NULL, clear_fragment_program, + &gxm_clear_fragment_program_patched); +} + /*########################################################################################################################* *---------------------------------------------------------General---------------------------------------------------------* @@ -228,17 +352,34 @@ void Gfx_Create(void) { Gfx.Created = true; InitGXM(); + Platform_LogConst("clear shader 1"); AllocRingBuffers(); + Platform_LogConst("clear shader 2"); AllocGXMContext(); + Platform_LogConst("clear shader 3"); AllocRenderTarget(); + Platform_LogConst("clear shader4"); for (int i = 0; i < NUM_DISPLAY_BUFFERS; i++) { AllocColorBuffer(i); } + Platform_LogConst("clear shader 5"); AllocDepthBuffer(); + Platform_LogConst("clear shader 6"); + AllocShaderPatcherMemory(); + Platform_LogConst("clear shader 7"); + AllocShaderPatcher(); + Platform_LogConst("clear shader 8"); + AllocClearShader(); + Platform_LogConst("clear shader 9"); + InitDefaultResources(); + Platform_LogConst("clear shader 10"); + + frontBufferIndex = NUM_DISPLAY_BUFFERS - 1; + backBufferIndex = 0; // 1x1 dummy white texture struct Bitmap bmp; @@ -292,8 +433,12 @@ void Gfx_SetFaceCulling(cc_bool enabled) { } // TODO void Gfx_SetAlphaBlending(cc_bool enabled) { } // TODO void Gfx_SetAlphaArgBlend(cc_bool enabled) { } +static float clear_color[4]; void Gfx_ClearCol(PackedCol color) { - // TODO + clear_color[0] = PackedCol_R(color) / 255.0f; + clear_color[1] = PackedCol_G(color) / 255.0f; + clear_color[2] = PackedCol_B(color) / 255.0f; + clear_color[3] = PackedCol_A(color) / 255.0f; } void Gfx_SetColWriteMask(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { @@ -363,57 +508,90 @@ void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) { } void Gfx_BeginFrame(void) { - // TODO + sceGxmBeginScene(gxm_context, + 0, gxm_render_target, + NULL, NULL, + gxm_sync_objects[backBufferIndex], + &gxm_color_surfaces[backBufferIndex], + &gxm_depth_stencil_surface); } -void Gfx_Clear(void) { } // TODO void Gfx_EndFrame(void) { Platform_LogConst("SWAP BUFFERS"); - // TODO + sceGxmEndScene(gxm_context, NULL, NULL); + + struct DQCallbackData cb_data; + cb_data.addr = gxm_color_surfaces_addr[backBufferIndex]; + + sceGxmDisplayQueueAddEntry(gxm_sync_objects[frontBufferIndex], + gxm_sync_objects[backBufferIndex], &cb_data); + + // Cycle through to next buffer pair + frontBufferIndex = backBufferIndex; + backBufferIndex = (backBufferIndex + 1) % NUM_DISPLAY_BUFFERS; + if (gfx_minFrameMs) LimitFPS(); } void Gfx_OnWindowResize(void) { } -/*########################################################################################################################* -*-------------------------------------------------------Index buffers-----------------------------------------------------* -*#########################################################################################################################*/ -GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { - //fillFunc(gfx_indices, count, obj); - return 1; -} - -void Gfx_BindIb(GfxResourceID ib) { } -void Gfx_DeleteIb(GfxResourceID* ib) { } - - /*########################################################################################################################* *----------------------------------------------------------Buffers--------------------------------------------------------* *#########################################################################################################################*/ -static void* gfx_vertices; -static int vb_size; +struct GPUBuffer { + void* data; + SceUID uid; +}; -GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) { - void* data = memalign(16, count * strideSizes[fmt]); - if (!data) Logger_Abort("Failed to allocate memory for GFX VB"); - return data; +struct GPUBuffer* GPUBuffer_Alloc(int size) { + struct GPUBuffer* buffer = Mem_Alloc(1, sizeof(struct GPUBuffer), "GPU buffer"); + + buffer->data = AllocGPUMemory(size, + SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, SCE_GXM_MEMORY_ATTRIB_READ, + &buffer->uid); + return buffer; +} + +static void GPUBuffer_Free(GfxResourceID* resource) { + GfxResourceID raw = *resource; + if (!raw) return; + + struct GPUBuffer* buffer = (struct GPUBuffer*)raw; + FreeGPUMemory(buffer->uid); + Mem_Free(buffer); + *resource = NULL; +} + + +static void* gfx_indices; + +GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { + struct GPUBuffer* buffer = GPUBuffer_Alloc(count * 2); + fillFunc(buffer->data, count, obj); + return buffer; +} + +void Gfx_BindIb(GfxResourceID ib) { // TODO + gfx_indices = ib; +} + +void Gfx_DeleteIb(GfxResourceID* ib) { GPUBuffer_Free(ib); } + + +static void* gfx_vertices; +GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) { + return GPUBuffer_Alloc(count * strideSizes[fmt]); } void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; } -void Gfx_DeleteVb(GfxResourceID* vb) { - GfxResourceID data = *vb; - if (data) Mem_Free(data); - *vb = 0; - // TODO -} +void Gfx_DeleteVb(GfxResourceID* vb) { GPUBuffer_Free(vb); } void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { - vb_size = count * strideSizes[fmt]; - return vb; - // TODO + struct GPUBuffer* buffer = (struct GPUBuffer*)vb; + return buffer->data; } void Gfx_UnlockVb(GfxResourceID vb) { @@ -423,26 +601,23 @@ void Gfx_UnlockVb(GfxResourceID vb) { GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { - void* data = memalign(16, maxVertices * strideSizes[fmt]); - if (!data) Logger_Abort("Failed to allocate memory for GFX VB"); - return data; - // TODO + return GPUBuffer_Alloc(maxVertices * strideSizes[fmt]); } void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { - vb_size = count * strideSizes[fmt]; - return vb; - // TODO + struct GPUBuffer* buffer = (struct GPUBuffer*)vb; + return buffer->data; } void Gfx_UnlockDynamicVb(GfxResourceID vb) { - gfx_vertices = vb; + gfx_vertices = vb; // TODO } void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { + struct GPUBuffer* buffer = (struct GPUBuffer*)vb; gfx_vertices = vb; - Mem_Copy(vb, vertices, vCount * gfx_stride); + Mem_Copy(buffer->data, vertices, vCount * gfx_stride); // TODO } @@ -526,4 +701,43 @@ void Gfx_DrawVb_IndexedTris(int verticesCount) { void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { // TODO } + + + + + + +void Gfx_Clear(void) { + static struct GPUBuffer* clear_vertices; + static struct GPUBuffer* clear_indices; + + if (!clear_vertices) { + clear_vertices = GPUBuffer_Alloc(4 * sizeof(struct clear_vertex)); + clear_indices = GPUBuffer_Alloc(4 * sizeof(unsigned short)); + + struct clear_vertex* clear_vertices_data = clear_vertices->data; + clear_vertices_data[0] = (struct clear_vertex){-1.0f, -1.0f}; + clear_vertices_data[1] = (struct clear_vertex){ 1.0f, -1.0f}; + clear_vertices_data[2] = (struct clear_vertex){-1.0f, 1.0f}; + clear_vertices_data[3] = (struct clear_vertex){ 1.0f, 1.0f}; + + unsigned short* clear_indices_data = clear_indices->data; + clear_indices_data[0] = 0; + clear_indices_data[1] = 1; + clear_indices_data[2] = 2; + clear_indices_data[3] = 3; + } + + sceGxmSetVertexProgram(gxm_context, gxm_clear_vertex_program_patched); + sceGxmSetFragmentProgram(gxm_context, gxm_clear_fragment_program_patched); + + void *uniform_buffer; + sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &uniform_buffer); + sceGxmSetUniformDataF(uniform_buffer, gxm_clear_fragment_program_clear_color_param, + 0, sizeof(clear_color) / sizeof(float), clear_color); + + sceGxmSetVertexStream(gxm_context, 0, clear_vertices->data); + sceGxmDraw(gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, + SCE_GXM_INDEX_FORMAT_U16, clear_indices->data, 4); +} #endif