mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
rsx: native RSX context, follow-ups
Give the RSX context and render interface proper IDs in libretro.h (RETRO_HW_CONTEXT_RSX = 11, RETRO_HW_RENDER_INTERFACE_RSX = 6) and ship one interface, version 1, with retire_memory in it, instead of two versions picked through the context's version_major. Retired memory goes on a ring and is covered by one label write per frame, with no wait-for-idle and no flush per call. Font vertex pages are all allocated with the font, and batches bigger than a page are drawn in page-sized pieces, so nothing is allocated while drawing. When the menu shows over a duped frame from a hardware core, the core's image is drawn behind it rather than the software texture. The frontend state reset runs only on frames the core rendered. The host mapping default stays 32 MB; RSX_HOST_SIZE still overrides it. The PSL1GHT guards around the new code are dropped: the driver only builds with HAVE_GCM, which only Makefile.psl1ght sets.
This commit is contained in:
1 parent
9ec7de02d3
commit
efe2158a48
7 files changed
+237
-266
No files matched your search
+4
-2
@@ -38,8 +38,10 @@ else
|
||||
endif
|
||||
|
||||
MACHDEP := -D__PSL1GHT__ -D__PS3__ -mcpu=cell
|
||||
RSX_HOST_SIZE ?= 16777216
|
||||
CFLAGS += -Wall $(DEFINES) $(MACHDEP) $(INCLUDE) -DRSX_HOST_SIZE=$(RSX_HOST_SIZE)
|
||||
CFLAGS += -Wall $(DEFINES) $(MACHDEP) $(INCLUDE)
|
||||
ifneq ($(RSX_HOST_SIZE),)
|
||||
CFLAGS += -DRSX_HOST_SIZE=$(RSX_HOST_SIZE)
|
||||
endif
|
||||
LDFLAGS := $(MACHDEP)
|
||||
LIBS += -lrt -laudio -lrsx -lgcm_sys -lnet -lio -lsysutil -lsysmodule -lm -llv2 -lnet -lnetctl -lsysfs -lcamera -lgem -lspurs
|
||||
|
||||
|
||||
+150
-190
@@ -49,9 +49,7 @@
|
||||
|
||||
#include "../../driver.h"
|
||||
#include "../../retroarch.h"
|
||||
#ifdef __PSL1GHT__
|
||||
#include <libretro_rsx.h>
|
||||
#endif
|
||||
#ifdef HAVE_THREADS
|
||||
#include "../video_thread_wrapper.h"
|
||||
#include "../display_servers/dispserv_ps3.h"
|
||||
@@ -64,10 +62,10 @@
|
||||
#define RSX_MAX_VERTICES 4
|
||||
#define RSX_MAX_TEXTURE_VERTICES 4096 /* Set > 0 for preallocated texture vertices */
|
||||
#define RSX_MAX_FONT_VERTICES 8192
|
||||
#ifdef __PSL1GHT__
|
||||
#define RSX_FONT_VERTEX_PAGES 8
|
||||
#define RSX_FONT_VERTEX_LABEL 198
|
||||
#endif
|
||||
/* Largest triangle-list draw that fits a page */
|
||||
#define RSX_FONT_VERTEX_CHUNK (RSX_MAX_FONT_VERTICES - RSX_MAX_FONT_VERTICES % 3)
|
||||
|
||||
#define RSX_SHADER_STOCK_BLEND (RSX_MAX_SHADERS - 1)
|
||||
#define RSX_SHADER_MENU (RSX_MAX_SHADERS - 2)
|
||||
@@ -217,14 +215,10 @@ typedef struct
|
||||
bool should_resize;
|
||||
bool msg_rendering_enabled;
|
||||
bool shared_context_use;
|
||||
#ifdef __PSL1GHT__
|
||||
struct retro_hw_render_interface_rsx hw_interface;
|
||||
struct retro_hw_render_interface_rsx_v2 hw_interface_v2;
|
||||
unsigned hw_interface_version;
|
||||
struct retro_rsx_image hw_image;
|
||||
bool hw_render;
|
||||
bool hw_image_valid;
|
||||
#endif
|
||||
} rsx_t;
|
||||
|
||||
#include "../font_driver.h"
|
||||
@@ -245,11 +239,10 @@ typedef struct
|
||||
|
||||
#define CB_SIZE 0x100000
|
||||
#ifndef RSX_HOST_SIZE
|
||||
#define RSX_HOST_SIZE (16*1024*1024)
|
||||
#define RSX_HOST_SIZE (32*1024*1024)
|
||||
#endif
|
||||
#define HOST_SIZE RSX_HOST_SIZE
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
static void *rsx_host_addr;
|
||||
|
||||
static bool rsx_set_hw_image(void *data, const struct retro_rsx_image *image)
|
||||
@@ -279,13 +272,9 @@ static bool rsx_get_hw_render_interface(void *data,
|
||||
if (!rsx || !iface || !rsx->hw_render
|
||||
|| rsx->video_info.is_threaded || !rsx_host_addr)
|
||||
return false;
|
||||
if (rsx->hw_interface_version >= 2)
|
||||
*iface = (const struct retro_hw_render_interface*)&rsx->hw_interface_v2;
|
||||
else
|
||||
*iface = (const struct retro_hw_render_interface*)&rsx->hw_interface;
|
||||
*iface = (const struct retro_hw_render_interface*)&rsx->hw_interface;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
#include <rsx/rsx.h>
|
||||
@@ -298,60 +287,68 @@ static bool rsx_get_hw_render_interface(void *data,
|
||||
#include <io/pad.h>
|
||||
#endif
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
#define RSX_RETIRED_MEMORY_COUNT 256
|
||||
#define RSX_RETIRED_MEMORY_COUNT 256 /* power of two */
|
||||
#define RSX_RETIRED_MEMORY_LABEL 199
|
||||
static struct
|
||||
{
|
||||
void *memory;
|
||||
uint32_t fence;
|
||||
} rsx_retired_memory[RSX_RETIRED_MEMORY_COUNT];
|
||||
static unsigned rsx_retired_memory_count;
|
||||
static unsigned rsx_retired_memory_head;
|
||||
static unsigned rsx_retired_memory_tail;
|
||||
/* Last fence written to the label */
|
||||
static uint32_t rsx_retired_memory_serial;
|
||||
static bool rsx_retired_memory_initialized;
|
||||
static bool rsx_retired_memory_queued;
|
||||
static bool rsx_labels_initialized;
|
||||
|
||||
static void rsx_collect_retired_memory(void)
|
||||
{
|
||||
unsigned i, kept = 0;
|
||||
uint32_t done;
|
||||
if (!rsx_retired_memory_count)
|
||||
if (rsx_retired_memory_head == rsx_retired_memory_tail)
|
||||
return;
|
||||
done = *(volatile uint32_t*)gcmGetLabelAddress(RSX_RETIRED_MEMORY_LABEL);
|
||||
for (i = 0; i < rsx_retired_memory_count; i++)
|
||||
if ((int32_t)(done - rsx_retired_memory[i].fence) >= 0)
|
||||
rsxFree(rsx_retired_memory[i].memory);
|
||||
else
|
||||
rsx_retired_memory[kept++] = rsx_retired_memory[i];
|
||||
rsx_retired_memory_count = kept;
|
||||
while (rsx_retired_memory_head != rsx_retired_memory_tail)
|
||||
{
|
||||
unsigned i = rsx_retired_memory_head & (RSX_RETIRED_MEMORY_COUNT - 1);
|
||||
if ((int32_t)(done - rsx_retired_memory[i].fence) < 0)
|
||||
break;
|
||||
rsxFree(rsx_retired_memory[i].memory);
|
||||
rsx_retired_memory_head++;
|
||||
}
|
||||
}
|
||||
|
||||
/* One fence per frame covers everything retired since the last one */
|
||||
static void rsx_fence_retired_memory(gcmContextData *context)
|
||||
{
|
||||
if (!rsx_retired_memory_queued)
|
||||
return;
|
||||
rsxSetWriteBackendLabel(context, RSX_RETIRED_MEMORY_LABEL,
|
||||
++rsx_retired_memory_serial);
|
||||
rsx_retired_memory_queued = false;
|
||||
}
|
||||
|
||||
static bool rsx_retire_hw_memory(void *data, void *memory)
|
||||
{
|
||||
unsigned i;
|
||||
rsx_t *rsx = (rsx_t*)data;
|
||||
uint32_t fence;
|
||||
if (!memory)
|
||||
return true;
|
||||
if (!rsx || !rsx->hw_render || rsx->video_info.is_threaded)
|
||||
return false;
|
||||
rsx_collect_retired_memory();
|
||||
if (rsx_retired_memory_count == RSX_RETIRED_MEMORY_COUNT)
|
||||
return false;
|
||||
if (!rsx_retired_memory_initialized)
|
||||
if (rsx_retired_memory_tail - rsx_retired_memory_head
|
||||
== RSX_RETIRED_MEMORY_COUNT)
|
||||
{
|
||||
*(volatile uint32_t*)gcmGetLabelAddress(RSX_RETIRED_MEMORY_LABEL) = 0;
|
||||
rsx_retired_memory_initialized = true;
|
||||
rsx_collect_retired_memory();
|
||||
if (rsx_retired_memory_tail - rsx_retired_memory_head
|
||||
== RSX_RETIRED_MEMORY_COUNT)
|
||||
return false;
|
||||
}
|
||||
fence = ++rsx_retired_memory_serial;
|
||||
if (!fence)
|
||||
fence = ++rsx_retired_memory_serial;
|
||||
rsx_retired_memory[rsx_retired_memory_count].memory = memory;
|
||||
rsx_retired_memory[rsx_retired_memory_count++].fence = fence;
|
||||
rsxSetWaitForIdle(rsx->context);
|
||||
rsxSetWriteBackendLabel(rsx->context, RSX_RETIRED_MEMORY_LABEL, fence);
|
||||
rsxFlushBuffer(rsx->context);
|
||||
i = rsx_retired_memory_tail++ & (RSX_RETIRED_MEMORY_COUNT - 1);
|
||||
rsx_retired_memory[i].memory = memory;
|
||||
rsx_retired_memory[i].fence = rsx_retired_memory_serial + 1;
|
||||
rsx_retired_memory_queued = true;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define rsx_context_bind_hw_render(rsx, enable) \
|
||||
if (rsx->shared_context_use) \
|
||||
@@ -365,27 +362,21 @@ static bool rsx_retire_hw_memory(void *data, void *memory)
|
||||
|
||||
#define MAX_MSG_LEN_CHUNK 64
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
typedef struct
|
||||
{
|
||||
rsx_vertex_t *vertices;
|
||||
unsigned capacity;
|
||||
unsigned used;
|
||||
u32 fence;
|
||||
} rsx_font_vertex_page_t;
|
||||
|
||||
static u32 rsx_font_vertex_serial;
|
||||
static bool rsx_font_vertex_label_initialized;
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rsx_t *rsx;
|
||||
rsx_vertex_t *vertices;
|
||||
#ifdef __PSL1GHT__
|
||||
rsx_font_vertex_page_t vertex_pages[RSX_FONT_VERTEX_PAGES];
|
||||
unsigned vertex_page;
|
||||
#endif
|
||||
rsx_texture_t texture;
|
||||
rsxProgramConst *proj_matrix;
|
||||
rsxProgramAttrib *pos_index;
|
||||
@@ -582,9 +573,7 @@ static void gfx_display_rsx_draw(gfx_display_ctx_draw_t *draw,
|
||||
GCM_LOCATION_RSX);
|
||||
|
||||
rsxClearSurface(rsx->context, GCM_CLEAR_Z);
|
||||
#ifdef __PSL1GHT__
|
||||
rsxInvalidateVertexCache(rsx->context);
|
||||
#endif
|
||||
rsxDrawVertexArray(rsx->context, GCM_TYPE_TRIANGLE_STRIP, 0, draw->coords->vertices);
|
||||
}
|
||||
|
||||
@@ -673,17 +662,12 @@ static void rsx_font_free(void *data,
|
||||
for (i = 0; i < font->retired_count; i++)
|
||||
rsxFree(font->retired[i]);
|
||||
}
|
||||
#ifdef __PSL1GHT__
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < RSX_FONT_VERTEX_PAGES; i++)
|
||||
if (font->vertex_pages[i].vertices)
|
||||
rsxFree(font->vertex_pages[i].vertices);
|
||||
}
|
||||
#else
|
||||
if (font->vertices)
|
||||
rsxFree(font->vertices);
|
||||
#endif
|
||||
|
||||
free(font);
|
||||
}
|
||||
@@ -785,18 +769,14 @@ static void *rsx_font_init(void *data,
|
||||
font->col_index = font->rsx->col_index[RSX_SHADER_STOCK_BLEND];
|
||||
font->tex_unit = font->rsx->tex_unit[RSX_SHADER_STOCK_BLEND];
|
||||
|
||||
if (!(font->vertices = (rsx_vertex_t *)rsxMemalign(128,
|
||||
sizeof(rsx_vertex_t) * RSX_MAX_FONT_VERTICES)))
|
||||
goto error;
|
||||
#ifdef __PSL1GHT__
|
||||
font->vertex_pages[0].vertices = font->vertices;
|
||||
font->vertex_pages[0].capacity = RSX_MAX_FONT_VERTICES;
|
||||
if (!rsx_font_vertex_label_initialized)
|
||||
{
|
||||
*(volatile u32*)gcmGetLabelAddress(RSX_FONT_VERTEX_LABEL) = 0;
|
||||
rsx_font_vertex_label_initialized = true;
|
||||
unsigned i;
|
||||
for (i = 0; i < RSX_FONT_VERTEX_PAGES; i++)
|
||||
if (!(font->vertex_pages[i].vertices = (rsx_vertex_t *)rsxMemalign(
|
||||
128, sizeof(rsx_vertex_t) * RSX_MAX_FONT_VERTICES)))
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
font->vertices = font->vertex_pages[0].vertices;
|
||||
font->rsx->font_vert_idx = 0;
|
||||
|
||||
/* The atlas may grow; the texture follows it */
|
||||
@@ -832,18 +812,19 @@ static int rsx_font_get_message_width(void *data, const char *msg,
|
||||
font->font_data, msg, msg_len, scale);
|
||||
}
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
static bool rsx_font_reserve_vertices(rsx_t *rsx, rsx_font_t *font,
|
||||
/* Returns how many of count vertices the current page now has room
|
||||
* for, at most a chunk; 0 while every other page is still on the GPU. */
|
||||
static unsigned rsx_font_reserve_vertices(rsx_t *rsx, rsx_font_t *font,
|
||||
unsigned count)
|
||||
{
|
||||
rsx_font_vertex_page_t *page = &font->vertex_pages[font->vertex_page];
|
||||
unsigned i;
|
||||
u32 done;
|
||||
|
||||
if (!count || count > (u32)-1 / sizeof(rsx_vertex_t))
|
||||
return false;
|
||||
if (!page->fence && count <= page->capacity - page->used)
|
||||
return true;
|
||||
if (count > RSX_FONT_VERTEX_CHUNK)
|
||||
count = RSX_FONT_VERTEX_CHUNK;
|
||||
if (!page->fence && count <= RSX_MAX_FONT_VERTICES - page->used)
|
||||
return count;
|
||||
|
||||
if (page->used && !page->fence)
|
||||
{
|
||||
@@ -859,37 +840,24 @@ static bool rsx_font_reserve_vertices(rsx_t *rsx, rsx_font_t *font,
|
||||
for (i = 0; i < RSX_FONT_VERTEX_PAGES; i++)
|
||||
{
|
||||
page = &font->vertex_pages[i];
|
||||
if (page->vertices && (!page->fence
|
||||
|| (int32_t)(done - page->fence) < 0))
|
||||
if (page->fence ? (int32_t)(done - page->fence) < 0 : page->used != 0)
|
||||
continue;
|
||||
if (page->capacity < count)
|
||||
{
|
||||
unsigned capacity = MAX(count, RSX_MAX_FONT_VERTICES);
|
||||
rsx_vertex_t *vertices = (rsx_vertex_t*)rsxMemalign(128,
|
||||
capacity * sizeof(rsx_vertex_t));
|
||||
if (!vertices)
|
||||
return false;
|
||||
if (page->vertices)
|
||||
rsxFree(page->vertices);
|
||||
page->vertices = vertices;
|
||||
page->capacity = capacity;
|
||||
}
|
||||
page->used = 0;
|
||||
page->fence = 0;
|
||||
font->vertices = page->vertices;
|
||||
font->vertex_page = i;
|
||||
return true;
|
||||
return count;
|
||||
}
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void rsx_font_draw_vertices(
|
||||
rsx_t *rsx,
|
||||
rsx_font_t *font,
|
||||
const video_coords_t *coords)
|
||||
{
|
||||
int i, end_vert_idx;
|
||||
unsigned i, count;
|
||||
unsigned remaining = coords->vertices;
|
||||
rsx_vertex_t *vertices = NULL;
|
||||
const float *vertex = coords->vertex;
|
||||
const float *tex_coord = coords->tex_coord;
|
||||
@@ -901,62 +869,52 @@ static void rsx_font_draw_vertices(
|
||||
font->atlas->dirty = false;
|
||||
}
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
if (!rsx_font_reserve_vertices(rsx, font, coords->vertices))
|
||||
return;
|
||||
rsx->font_vert_idx = font->vertex_pages[font->vertex_page].used;
|
||||
end_vert_idx = rsx->font_vert_idx + coords->vertices;
|
||||
#else
|
||||
end_vert_idx = rsx->font_vert_idx + coords->vertices;
|
||||
if (end_vert_idx > RSX_MAX_FONT_VERTICES)
|
||||
{
|
||||
rsx->font_vert_idx = 0;
|
||||
end_vert_idx = rsx->font_vert_idx + coords->vertices;
|
||||
}
|
||||
#endif
|
||||
vertices = font->vertices;
|
||||
|
||||
for (i = rsx->font_vert_idx; i < end_vert_idx; i++)
|
||||
{
|
||||
vertices[i].x = *vertex++;
|
||||
vertices[i].y = *vertex++;
|
||||
vertices[i].u = *tex_coord++;
|
||||
vertices[i].v = *tex_coord++;
|
||||
vertices[i].r = *color++;
|
||||
vertices[i].g = *color++;
|
||||
vertices[i].b = *color++;
|
||||
vertices[i].a = *color++;
|
||||
}
|
||||
|
||||
rsxAddressToOffset(&vertices[rsx->font_vert_idx].x, &font->pos_offset);
|
||||
rsxAddressToOffset(&vertices[rsx->font_vert_idx].u, &font->uv_offset);
|
||||
rsxAddressToOffset(&vertices[rsx->font_vert_idx].r, &font->col_offset);
|
||||
rsx->font_vert_idx = end_vert_idx;
|
||||
#ifdef __PSL1GHT__
|
||||
font->vertex_pages[font->vertex_page].used = end_vert_idx;
|
||||
#endif
|
||||
|
||||
rsxBindVertexArrayAttrib(rsx->context, font->pos_index->index, 0,
|
||||
font->pos_offset, sizeof(rsx_vertex_t), 2,
|
||||
GCM_VERTEX_DATA_TYPE_F32, GCM_LOCATION_RSX);
|
||||
rsxBindVertexArrayAttrib(rsx->context, font->uv_index->index, 0,
|
||||
font->uv_offset, sizeof(rsx_vertex_t), 2,
|
||||
GCM_VERTEX_DATA_TYPE_F32, GCM_LOCATION_RSX);
|
||||
rsxBindVertexArrayAttrib(rsx->context, font->col_index->index, 0,
|
||||
font->col_offset, sizeof(rsx_vertex_t), 4,
|
||||
GCM_VERTEX_DATA_TYPE_F32, GCM_LOCATION_RSX);
|
||||
|
||||
rsxLoadVertexProgram(rsx->context, font->vpo, font->vp_ucode);
|
||||
rsxSetVertexProgramParameter(rsx->context, font->vpo,
|
||||
font->proj_matrix, (float *)&rsx->mvp_no_rot);
|
||||
rsxLoadFragmentProgramLocation(rsx->context, font->fpo,
|
||||
font->fp_offset, GCM_LOCATION_RSX);
|
||||
|
||||
rsxClearSurface(rsx->context, GCM_CLEAR_Z);
|
||||
#ifdef __PSL1GHT__
|
||||
rsxInvalidateVertexCache(rsx->context);
|
||||
#endif
|
||||
rsxDrawVertexArray(rsx->context, GCM_TYPE_TRIANGLES, 0, coords->vertices);
|
||||
|
||||
while (remaining)
|
||||
{
|
||||
rsx_font_vertex_page_t *page;
|
||||
if (!(count = rsx_font_reserve_vertices(rsx, font, remaining)))
|
||||
return;
|
||||
page = &font->vertex_pages[font->vertex_page];
|
||||
vertices = font->vertices + page->used;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
vertices[i].x = *vertex++;
|
||||
vertices[i].y = *vertex++;
|
||||
vertices[i].u = *tex_coord++;
|
||||
vertices[i].v = *tex_coord++;
|
||||
vertices[i].r = *color++;
|
||||
vertices[i].g = *color++;
|
||||
vertices[i].b = *color++;
|
||||
vertices[i].a = *color++;
|
||||
}
|
||||
|
||||
rsxAddressToOffset(&vertices[0].x, &font->pos_offset);
|
||||
rsxAddressToOffset(&vertices[0].u, &font->uv_offset);
|
||||
rsxAddressToOffset(&vertices[0].r, &font->col_offset);
|
||||
page->used += count;
|
||||
rsx->font_vert_idx = page->used;
|
||||
remaining -= count;
|
||||
|
||||
rsxBindVertexArrayAttrib(rsx->context, font->pos_index->index, 0,
|
||||
font->pos_offset, sizeof(rsx_vertex_t), 2,
|
||||
GCM_VERTEX_DATA_TYPE_F32, GCM_LOCATION_RSX);
|
||||
rsxBindVertexArrayAttrib(rsx->context, font->uv_index->index, 0,
|
||||
font->uv_offset, sizeof(rsx_vertex_t), 2,
|
||||
GCM_VERTEX_DATA_TYPE_F32, GCM_LOCATION_RSX);
|
||||
rsxBindVertexArrayAttrib(rsx->context, font->col_index->index, 0,
|
||||
font->col_offset, sizeof(rsx_vertex_t), 4,
|
||||
GCM_VERTEX_DATA_TYPE_F32, GCM_LOCATION_RSX);
|
||||
rsxInvalidateVertexCache(rsx->context);
|
||||
rsxDrawVertexArray(rsx->context, GCM_TYPE_TRIANGLES, 0, count);
|
||||
}
|
||||
}
|
||||
|
||||
#define RSX_FONT_FLUSH() \
|
||||
@@ -1401,11 +1359,9 @@ static const gfx_ctx_driver_t* rsx_get_context(rsx_t* rsx)
|
||||
&& (hwr->context_type != RETRO_HW_CONTEXT_NONE))
|
||||
rsx->shared_context_use = true;
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
/* Native RSX uses one command FIFO, not separate GL contexts. */
|
||||
if (hwr->context_type == RETRO_HW_CONTEXT_RSX)
|
||||
rsx->shared_context_use = false;
|
||||
#endif
|
||||
|
||||
gfx_ctx = video_context_driver_init_first(rsx,
|
||||
settings->arrays.video_context_driver,
|
||||
@@ -1526,9 +1482,7 @@ static gcmContextData *rsx_init_screen(rsx_t* gcm)
|
||||
if (!context)
|
||||
goto error;
|
||||
saved_context = context;
|
||||
#ifdef __PSL1GHT__
|
||||
rsx_host_addr = host_addr;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
context = saved_context;
|
||||
@@ -1801,7 +1755,12 @@ static void* rsx_init(const video_info_t* video)
|
||||
if (video->font_enable)
|
||||
rsx->msg_rendering_enabled = true;
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
if (!rsx_labels_initialized)
|
||||
{
|
||||
*(volatile u32*)gcmGetLabelAddress(RSX_FONT_VERTEX_LABEL) = 0;
|
||||
*(volatile u32*)gcmGetLabelAddress(RSX_RETIRED_MEMORY_LABEL) = 0;
|
||||
rsx_labels_initialized = true;
|
||||
}
|
||||
rsx->hw_render = video_driver_get_hw_context()->context_type
|
||||
== RETRO_HW_CONTEXT_RSX;
|
||||
rsx->hw_interface.interface_type = RETRO_HW_RENDER_INTERFACE_RSX;
|
||||
@@ -1812,12 +1771,7 @@ static void* rsx_init(const video_info_t* video)
|
||||
rsx->hw_interface.io_size = HOST_SIZE;
|
||||
rsx->hw_interface.io_used = CB_SIZE + 64 * 1024;
|
||||
rsx->hw_interface.set_image = rsx_set_hw_image;
|
||||
rsx->hw_interface_v2.base = rsx->hw_interface;
|
||||
rsx->hw_interface_v2.base.interface_version = RETRO_HW_RENDER_INTERFACE_RSX_V2_VERSION;
|
||||
rsx->hw_interface_v2.retire_memory = rsx_retire_hw_memory;
|
||||
rsx->hw_interface_version = video_driver_get_hw_context()->version_major;
|
||||
rsx_collect_retired_memory();
|
||||
#endif
|
||||
rsx->hw_interface.retire_memory = rsx_retire_hw_memory;
|
||||
return rsx;
|
||||
|
||||
error:
|
||||
@@ -2633,6 +2587,35 @@ static void rsx_update_screen(rsx_t* gcm)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void rsx_draw_hw_image(rsx_t *gcm)
|
||||
{
|
||||
rsx_texture_t texture;
|
||||
memset(&texture, 0, sizeof(texture));
|
||||
texture.tex.format = GCM_TEXTURE_FORMAT_A8R8G8B8 | GCM_TEXTURE_FORMAT_LIN;
|
||||
texture.tex.mipmap = 1;
|
||||
texture.tex.dimension = GCM_TEXTURE_DIMS_2D;
|
||||
texture.tex.remap = GCM_TEXTURE_REMAP_TYPE_REMAP << GCM_TEXTURE_REMAP_TYPE_B_SHIFT
|
||||
| GCM_TEXTURE_REMAP_TYPE_REMAP << GCM_TEXTURE_REMAP_TYPE_G_SHIFT
|
||||
| GCM_TEXTURE_REMAP_TYPE_REMAP << GCM_TEXTURE_REMAP_TYPE_R_SHIFT
|
||||
| GCM_TEXTURE_REMAP_TYPE_REMAP << GCM_TEXTURE_REMAP_TYPE_A_SHIFT
|
||||
| GCM_TEXTURE_REMAP_COLOR_A << GCM_TEXTURE_REMAP_COLOR_A_SHIFT
|
||||
| GCM_TEXTURE_REMAP_COLOR_R << GCM_TEXTURE_REMAP_COLOR_R_SHIFT
|
||||
| GCM_TEXTURE_REMAP_COLOR_G << GCM_TEXTURE_REMAP_COLOR_G_SHIFT
|
||||
| GCM_TEXTURE_REMAP_COLOR_B << GCM_TEXTURE_REMAP_COLOR_B_SHIFT;
|
||||
texture.tex.width = gcm->hw_image.width;
|
||||
texture.tex.height = gcm->hw_image.height;
|
||||
texture.tex.depth = 1;
|
||||
texture.tex.pitch = gcm->hw_image.pitch;
|
||||
texture.tex.offset = gcm->hw_image.offset;
|
||||
texture.tex.location = GCM_LOCATION_RSX;
|
||||
texture.min_filter = gcm->smooth ? GCM_TEXTURE_LINEAR : GCM_TEXTURE_NEAREST;
|
||||
texture.mag_filter = texture.min_filter;
|
||||
texture.wrap_s = GCM_TEXTURE_CLAMP_TO_EDGE;
|
||||
texture.wrap_t = GCM_TEXTURE_CLAMP_TO_EDGE;
|
||||
rsx_set_texture(gcm, &texture);
|
||||
rsx_draw_vertices(gcm);
|
||||
}
|
||||
|
||||
static bool rsx_frame(void* data, const void* frame,
|
||||
unsigned dims,
|
||||
uint64_t frame_count,
|
||||
@@ -2653,9 +2636,10 @@ static bool rsx_frame(void* data, const void* frame,
|
||||
#endif
|
||||
bool draw = false;
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
rsx_collect_retired_memory();
|
||||
if (gcm->hw_render)
|
||||
rsx_fence_retired_memory(gcm->context);
|
||||
/* The core shares the FIFO and leaves its own state behind */
|
||||
if (gcm->hw_render && frame == RETRO_HW_FRAME_BUFFER_VALID)
|
||||
{
|
||||
unsigned attrib;
|
||||
rsxSetSurface(gcm->context, &gcm->surface[gcm->nextBuffer]);
|
||||
@@ -2679,7 +2663,6 @@ static bool rsx_frame(void* data, const void* frame,
|
||||
rsxBindVertexArrayAttrib(gcm->context, attrib, 0, 0,
|
||||
0, 0, GCM_VERTEX_DATA_TYPE_F32, GCM_LOCATION_RSX);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (gcm->should_resize)
|
||||
rsx_update_viewport(gcm);
|
||||
@@ -2705,42 +2688,15 @@ static bool rsx_frame(void* data, const void* frame,
|
||||
VIDEO_SCALE_H(vp.dims), vp.min, vp.max,
|
||||
vp.scale, vp.offset);
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
if (frame == RETRO_HW_FRAME_BUFFER_VALID)
|
||||
{
|
||||
if (gcm->hw_render && gcm->hw_image_valid)
|
||||
{
|
||||
rsx_texture_t texture;
|
||||
memset(&texture, 0, sizeof(texture));
|
||||
texture.tex.format = GCM_TEXTURE_FORMAT_A8R8G8B8 | GCM_TEXTURE_FORMAT_LIN;
|
||||
texture.tex.mipmap = 1;
|
||||
texture.tex.dimension = GCM_TEXTURE_DIMS_2D;
|
||||
texture.tex.remap = GCM_TEXTURE_REMAP_TYPE_REMAP << GCM_TEXTURE_REMAP_TYPE_B_SHIFT
|
||||
| GCM_TEXTURE_REMAP_TYPE_REMAP << GCM_TEXTURE_REMAP_TYPE_G_SHIFT
|
||||
| GCM_TEXTURE_REMAP_TYPE_REMAP << GCM_TEXTURE_REMAP_TYPE_R_SHIFT
|
||||
| GCM_TEXTURE_REMAP_TYPE_REMAP << GCM_TEXTURE_REMAP_TYPE_A_SHIFT
|
||||
| GCM_TEXTURE_REMAP_COLOR_A << GCM_TEXTURE_REMAP_COLOR_A_SHIFT
|
||||
| GCM_TEXTURE_REMAP_COLOR_R << GCM_TEXTURE_REMAP_COLOR_R_SHIFT
|
||||
| GCM_TEXTURE_REMAP_COLOR_G << GCM_TEXTURE_REMAP_COLOR_G_SHIFT
|
||||
| GCM_TEXTURE_REMAP_COLOR_B << GCM_TEXTURE_REMAP_COLOR_B_SHIFT;
|
||||
texture.tex.width = gcm->hw_image.width;
|
||||
texture.tex.height = gcm->hw_image.height;
|
||||
texture.tex.depth = 1;
|
||||
texture.tex.pitch = gcm->hw_image.pitch;
|
||||
texture.tex.offset = gcm->hw_image.offset;
|
||||
texture.tex.location = GCM_LOCATION_RSX;
|
||||
texture.min_filter = gcm->smooth ? GCM_TEXTURE_LINEAR : GCM_TEXTURE_NEAREST;
|
||||
texture.mag_filter = texture.min_filter;
|
||||
texture.wrap_s = GCM_TEXTURE_CLAMP_TO_EDGE;
|
||||
texture.wrap_t = GCM_TEXTURE_CLAMP_TO_EDGE;
|
||||
rsx_set_texture(gcm, &texture);
|
||||
rsx_draw_vertices(gcm);
|
||||
rsx_draw_hw_image(gcm);
|
||||
draw = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (frame && width && height)
|
||||
else if (frame && width && height)
|
||||
{
|
||||
gcm->tex_index = ((gcm->tex_index + 1) % RSX_MAX_TEXTURES);
|
||||
if (rsx_load_texture_data(gcm,
|
||||
@@ -2763,10 +2719,18 @@ static bool rsx_frame(void* data, const void* frame,
|
||||
{
|
||||
/* A duped core frame stays behind the menu: the surface was
|
||||
* cleared at the last flip */
|
||||
if (!draw && gcm->texture[gcm->tex_index].data)
|
||||
if (!draw)
|
||||
{
|
||||
rsx_set_texture(gcm, &gcm->texture[gcm->tex_index]);
|
||||
rsx_draw_vertices(gcm);
|
||||
if (gcm->hw_render)
|
||||
{
|
||||
if (gcm->hw_image_valid)
|
||||
rsx_draw_hw_image(gcm);
|
||||
}
|
||||
else if (gcm->texture[gcm->tex_index].data)
|
||||
{
|
||||
rsx_set_texture(gcm, &gcm->texture[gcm->tex_index]);
|
||||
rsx_draw_vertices(gcm);
|
||||
}
|
||||
}
|
||||
menu_driver_frame(menu_is_alive, video_info);
|
||||
draw = true;
|
||||
@@ -3091,11 +3055,7 @@ static const video_poke_interface_t rsx_poke_interface = {
|
||||
NULL, /* grab_mouse_toggle */
|
||||
NULL, /* get_current_shader */
|
||||
NULL, /* get_current_software_framebuffer */
|
||||
#ifdef __PSL1GHT__
|
||||
rsx_get_hw_render_interface,
|
||||
#else
|
||||
NULL, /* get_hw_render_interface */
|
||||
#endif
|
||||
NULL, /* set_hdr_menu_nits */
|
||||
NULL, /* set_hdr_paper_white_nits */
|
||||
NULL, /* set_hdr_expand_gamut */
|
||||
|
||||
+6
-9
@@ -40,9 +40,6 @@
|
||||
#include <formats/video_hw_frame.h>
|
||||
#include "../cores/internal_cores.h"
|
||||
#include "video_driver.h"
|
||||
#if defined(__PSL1GHT__) && defined(HAVE_GCM)
|
||||
#include <libretro_rsx.h>
|
||||
#endif
|
||||
#include "video_hdr_metadata.h"
|
||||
#include "gfx_media_display.h"
|
||||
#if defined(HAVE_X11) && defined(HAVE_XRANDR)
|
||||
@@ -1912,7 +1909,7 @@ video_driver_t *hw_render_context_driver(
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
#if defined(__PSL1GHT__) && defined(HAVE_GCM)
|
||||
#ifdef HAVE_GCM
|
||||
case RETRO_HW_CONTEXT_RSX:
|
||||
return &video_gcm;
|
||||
#endif
|
||||
@@ -1972,7 +1969,7 @@ const char *hw_render_context_name(
|
||||
if (type == RETRO_HW_CONTEXT_D3D12)
|
||||
return "d3d12";
|
||||
#endif
|
||||
#if defined(__PSL1GHT__) && defined(HAVE_GCM)
|
||||
#ifdef HAVE_GCM
|
||||
if (type == RETRO_HW_CONTEXT_RSX)
|
||||
return "rsx";
|
||||
#endif
|
||||
@@ -2013,7 +2010,7 @@ static enum retro_hw_context_type hw_render_context_type(const char *s)
|
||||
if (string_is_equal(s, "d3d12"))
|
||||
return RETRO_HW_CONTEXT_D3D12;
|
||||
#endif
|
||||
#if defined(__PSL1GHT__) && defined(HAVE_GCM)
|
||||
#ifdef HAVE_GCM
|
||||
if (string_is_equal(s, "rsx"))
|
||||
return RETRO_HW_CONTEXT_RSX;
|
||||
#endif
|
||||
@@ -5609,7 +5606,7 @@ bool video_driver_find_driver(
|
||||
{
|
||||
switch (rdr_type)
|
||||
{
|
||||
#if defined(__PSL1GHT__) && defined(HAVE_GCM)
|
||||
#ifdef HAVE_GCM
|
||||
case RETRO_HW_CONTEXT_RSX:
|
||||
#endif
|
||||
case RETRO_HW_CONTEXT_OPENGL_CORE:
|
||||
@@ -5618,7 +5615,7 @@ bool video_driver_find_driver(
|
||||
case RETRO_HW_CONTEXT_D3D10:
|
||||
case RETRO_HW_CONTEXT_D3D11:
|
||||
case RETRO_HW_CONTEXT_D3D12:
|
||||
#if defined(HAVE_VULKAN) || defined(HAVE_D3D9) || defined(HAVE_D3D10) || defined(HAVE_D3D11) || defined(HAVE_D3D12) || defined(HAVE_OPENGL_CORE) || (defined(__PSL1GHT__) && defined(HAVE_GCM))
|
||||
#if defined(HAVE_VULKAN) || defined(HAVE_D3D9) || defined(HAVE_D3D10) || defined(HAVE_D3D11) || defined(HAVE_D3D12) || defined(HAVE_OPENGL_CORE) || defined(HAVE_GCM)
|
||||
RARCH_LOG("[Video] Using HW render, %s driver forced.\n",
|
||||
rdr_context_name);
|
||||
|
||||
@@ -5740,7 +5737,7 @@ bool video_driver_is_hw_context(void)
|
||||
|
||||
bool video_driver_render_context_is_main_thread_only(void)
|
||||
{
|
||||
#if defined(__PSL1GHT__) && defined(HAVE_GCM)
|
||||
#ifdef HAVE_GCM
|
||||
if (video_driver_st.hw_render.context_type == RETRO_HW_CONTEXT_RSX)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
@@ -4496,6 +4496,12 @@ enum retro_hw_render_interface_type
|
||||
*/
|
||||
RETRO_HW_RENDER_INTERFACE_GSKIT_PS2 = 5,
|
||||
|
||||
/**
|
||||
* PlayStation 3 RSX (PSL1GHT).
|
||||
* @see retro_hw_render_interface_rsx in libretro_rsx.h
|
||||
*/
|
||||
RETRO_HW_RENDER_INTERFACE_RSX = 6,
|
||||
|
||||
/** @private Defined to ensure <tt>sizeof(retro_hw_render_interface_type) == sizeof(int)</tt>.
|
||||
* Do not use. */
|
||||
RETRO_HW_RENDER_INTERFACE_DUMMY = INT_MAX
|
||||
@@ -6589,6 +6595,9 @@ enum retro_hw_context_type
|
||||
/* Direct3D9, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE */
|
||||
RETRO_HW_CONTEXT_D3D9 = 10,
|
||||
|
||||
/* PlayStation 3 RSX, see libretro_rsx.h */
|
||||
RETRO_HW_CONTEXT_RSX = 11,
|
||||
|
||||
/** Dummy value to ensure sizeof(enum retro_hw_context_type) == sizeof(int). Do not use. */
|
||||
RETRO_HW_CONTEXT_DUMMY = INT_MAX
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
/* Copyright (C) 2010-2026 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this libretro API header (libretro_rsx.h)
|
||||
@@ -29,9 +29,6 @@
|
||||
|
||||
#include "libretro.h"
|
||||
|
||||
/* Experimental extension IDs, not upstream-assigned libretro values. */
|
||||
#define RETRO_HW_CONTEXT_RSX ((enum retro_hw_context_type)0x525358)
|
||||
#define RETRO_HW_RENDER_INTERFACE_RSX ((enum retro_hw_render_interface_type)0x525358)
|
||||
#define RETRO_HW_RENDER_INTERFACE_RSX_VERSION 1
|
||||
|
||||
/* Linear A8R8G8B8 texture in RSX local memory. The core owns the allocation
|
||||
@@ -46,7 +43,8 @@ struct retro_rsx_image
|
||||
|
||||
/* Query with GET_HW_RENDER_INTERFACE from context_reset, after requesting
|
||||
* RETRO_HW_CONTEXT_RSX through SET_HW_RENDER. Valid until context_destroy.
|
||||
* Both callers must submit commands on the main thread. */
|
||||
* Both callers must submit commands on the main thread.
|
||||
* Labels 198 and 199 belong to the frontend. */
|
||||
struct retro_hw_render_interface_rsx
|
||||
{
|
||||
enum retro_hw_render_interface_type interface_type;
|
||||
@@ -61,17 +59,9 @@ struct retro_hw_render_interface_rsx
|
||||
/* Publish an image before video_refresh(RETRO_HW_FRAME_BUFFER_VALID).
|
||||
* NULL releases the cached image. No allocation or CPU wait is performed. */
|
||||
bool (*set_image)(void *handle, const struct retro_rsx_image *image);
|
||||
};
|
||||
|
||||
/* Request context version 2 for nonblocking retirement of local allocations.
|
||||
* Version 1 clients continue receiving the version 1 interface. */
|
||||
#define RETRO_HW_RENDER_INTERFACE_RSX_V2_VERSION 2
|
||||
struct retro_hw_render_interface_rsx_v2
|
||||
{
|
||||
struct retro_hw_render_interface_rsx base;
|
||||
/* Transfers ownership of an rsxMemalign allocation to the frontend.
|
||||
* It is freed after submitted commands finish. NULL is accepted.
|
||||
* Label 199 belongs to the frontend. Returns false if the queue is full. */
|
||||
/* Transfers ownership of an rsxMemalign allocation to the frontend,
|
||||
* freed once the commands submitted before the next video_refresh have
|
||||
* finished. NULL is accepted. Returns false if the queue is full. */
|
||||
bool (*retire_memory)(void *handle, void *memory);
|
||||
};
|
||||
|
||||
|
||||
@@ -71,9 +71,6 @@
|
||||
#include <encodings/utf.h>
|
||||
|
||||
#include <libretro.h>
|
||||
#if defined(__PSL1GHT__) && defined(HAVE_GCM)
|
||||
#include <libretro_rsx.h>
|
||||
#endif
|
||||
#ifdef HAVE_RMP4
|
||||
#include <formats/rh264.h>
|
||||
#endif
|
||||
@@ -1225,7 +1222,7 @@ static bool dynamic_verify_hw_context(
|
||||
size_t len = strlen(video_ident);
|
||||
switch (type)
|
||||
{
|
||||
#if defined(__PSL1GHT__) && defined(HAVE_GCM)
|
||||
#ifdef HAVE_GCM
|
||||
case RETRO_HW_CONTEXT_RSX:
|
||||
if (!(len == 3 && memcmp(video_ident, "rsx", 3) == 0))
|
||||
return false;
|
||||
@@ -1312,10 +1309,8 @@ static bool dynamic_request_hw_context(enum retro_hw_context_type type,
|
||||
RARCH_LOG("[HW] Requesting no HW context.\n");
|
||||
break;
|
||||
|
||||
#if defined(__PSL1GHT__) && defined(HAVE_GCM)
|
||||
#ifdef HAVE_GCM
|
||||
case RETRO_HW_CONTEXT_RSX:
|
||||
if (major > 2 || minor != 0)
|
||||
return false;
|
||||
RARCH_LOG("[HW] Requesting RSX context.\n");
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
* vertices land where the RSX is pointed at, inside their buffer,
|
||||
* and vertices queued for the RSX are not written over by the next
|
||||
* draw, message or frame.
|
||||
* - font_batches: large batches, independent font cursors and GPU fences.
|
||||
* - font_batches: large batches split into draws, independent font
|
||||
* cursors and GPU fences.
|
||||
* - native_menu_frame, menu_dupe_frame: a menu with no new core
|
||||
* frame is presented, over the last core frame if there is one.
|
||||
*
|
||||
@@ -856,18 +857,19 @@ static void test_font_queue(void)
|
||||
printf("font_queue: ok\n");
|
||||
}
|
||||
|
||||
/* Ozone batches may exceed the initial font buffer. */
|
||||
/* Ozone batches may exceed a font page: they are split into page-sized
|
||||
* draws, nothing is allocated and nothing still on the GPU is reused. */
|
||||
static void test_font_batches(void)
|
||||
{
|
||||
video_coords_t coords;
|
||||
rsx_t *rsx = driver_up();
|
||||
rsx_font_t *font = (rsx_font_t*)rsx_font_init(rsx, NULL, 12.0f, false);
|
||||
rsx_t *rsx = driver_up();
|
||||
rsx_font_t *font = (rsx_font_t*)rsx_font_init(rsx, NULL, 12.0f, false);
|
||||
rsx_font_t *other = (rsx_font_t*)rsx_font_init(rsx, NULL, 12.0f, false);
|
||||
unsigned count = 9384;
|
||||
float *data = (float*)malloc(count * 8 * sizeof(float));
|
||||
rsx_vertex_t *queued[RSX_FONT_VERTEX_PAGES];
|
||||
unsigned i, draws, live, finishes = rsx_finish_calls;
|
||||
unsigned first_draw = rsx_draw_calls;
|
||||
unsigned count = 9384;
|
||||
float *data = (float*)malloc(count * 8 * sizeof(float));
|
||||
float first[RSX_FONT_VERTEX_PAGES];
|
||||
unsigned i, draws, allocations, finishes = rsx_finish_calls;
|
||||
unsigned first_draw = rsx_draw_calls;
|
||||
unsigned invalidations = rsx_vertex_invalidations;
|
||||
CHECK(font && other && data, "font_batches: allocation");
|
||||
if (!font || !other || !data)
|
||||
@@ -888,42 +890,44 @@ static void test_font_batches(void)
|
||||
"font_batches: other font moved cursor");
|
||||
|
||||
fake_defer_backend = true;
|
||||
coords.vertices = count;
|
||||
draws = rsx_draw_calls;
|
||||
live = rsx_live();
|
||||
rsx_fail_at = rsx_alloc_calls + 1;
|
||||
coords.vertices = count;
|
||||
allocations = rsx_alloc_calls;
|
||||
draws = rsx_draw_calls;
|
||||
rsx_font_draw_vertices(rsx, font, &coords);
|
||||
CHECK(rsx_draw_calls == draws && rsx_live() == live,
|
||||
"font_batches: allocation failure submitted a draw");
|
||||
CHECK(font->vertices[0].r == 1.0f,
|
||||
"font_batches: allocation failure overwrote queued text");
|
||||
rsx_fail_at = 0;
|
||||
fake_labels[RSX_FONT_VERTEX_LABEL] = rsx_font_vertex_serial;
|
||||
for (i = 0; i < RSX_FONT_VERTEX_PAGES; i++)
|
||||
CHECK(rsx_draw_calls == draws + 2,
|
||||
"font_batches: oversized batch not split into page-sized draws");
|
||||
CHECK(font->vertex_pages[font->vertex_page].used
|
||||
== count - RSX_FONT_VERTEX_CHUNK
|
||||
&& font->vertices[count - RSX_FONT_VERTEX_CHUNK - 1].a == 1.0f,
|
||||
"font_batches: oversized batch truncated");
|
||||
|
||||
/* Fill pages until every one is waiting on the GPU */
|
||||
for (i = 0; i < RSX_FONT_VERTEX_PAGES * 2; i++)
|
||||
{
|
||||
data[count * 4] = (float)(i + 2);
|
||||
draws = rsx_draw_calls;
|
||||
rsx_font_draw_vertices(rsx, font, &coords);
|
||||
queued[i] = font->vertices;
|
||||
CHECK(font->vertex_pages[font->vertex_page].capacity >= count,
|
||||
"font_batches: oversized batch outside allocation");
|
||||
CHECK(font->vertices[count - 1].a == 1.0f,
|
||||
"font_batches: oversized batch truncated");
|
||||
if (rsx_draw_calls != draws + 2)
|
||||
break;
|
||||
}
|
||||
CHECK(i < RSX_FONT_VERTEX_PAGES * 2,
|
||||
"font_batches: pages never ran out with the GPU stalled");
|
||||
for (i = 0; i < RSX_FONT_VERTEX_PAGES; i++)
|
||||
first[i] = font->vertex_pages[i].vertices[0].r;
|
||||
draws = rsx_draw_calls;
|
||||
data[count * 4] = -1.0f;
|
||||
rsx_font_draw_vertices(rsx, font, &coords);
|
||||
CHECK(rsx_draw_calls == draws,
|
||||
"font_batches: reused a buffer still on the GPU");
|
||||
for (i = 0; i < RSX_FONT_VERTEX_PAGES; i++)
|
||||
CHECK(queued[i][0].r == (float)(i + 2),
|
||||
CHECK(font->vertex_pages[i].vertices[0].r == first[i],
|
||||
"font_batches: pending page %u overwritten", i);
|
||||
fake_labels[RSX_FONT_VERTEX_LABEL] = rsx_font_vertex_serial;
|
||||
rsx_font_draw_vertices(rsx, font, &coords);
|
||||
CHECK(rsx_draw_calls == draws + 1,
|
||||
CHECK(rsx_draw_calls == draws + 2,
|
||||
"font_batches: completed pages not reused");
|
||||
draws = rsx_draw_calls;
|
||||
coords.vertices = (unsigned)-1;
|
||||
rsx_font_draw_vertices(rsx, font, &coords);
|
||||
CHECK(rsx_draw_calls == draws, "font_batches: size overflow accepted");
|
||||
CHECK(rsx_alloc_calls == allocations,
|
||||
"font_batches: allocated while drawing");
|
||||
CHECK(rsx_finish_calls == finishes, "font_batches: waits for the GPU");
|
||||
CHECK(rsx_vertex_invalidations - invalidations
|
||||
== rsx_draw_calls - first_draw,
|
||||
@@ -1025,6 +1029,14 @@ static void test_hw_interface(void)
|
||||
"hw_interface: GPU image displayed without allocation or CPU upload");
|
||||
CHECK(rsx_finish_calls == finishes,
|
||||
"hw_interface: handoff does not wait for the GPU");
|
||||
info.menu_st_flags = MENU_ST_FLAG_ALIVE;
|
||||
rsx->menu_frame_enable = true;
|
||||
draws = rsx_draw_calls;
|
||||
rsx_frame(rsx, NULL, 0, 1, 0, NULL, &info);
|
||||
CHECK(rsx_draw_calls == draws + 1,
|
||||
"hw_interface: core image not drawn again behind the menu");
|
||||
info.menu_st_flags = 0;
|
||||
rsx->menu_frame_enable = false;
|
||||
image.pitch = 1;
|
||||
CHECK(!iface->set_image(iface->handle, &image),
|
||||
"hw_interface: invalid pitch rejected");
|
||||
@@ -1043,39 +1055,45 @@ static void test_hw_interface(void)
|
||||
printf("hw_interface: ok\n");
|
||||
}
|
||||
|
||||
/* Retired memory is fenced once at the next frame and freed when the
|
||||
* GPU passes it, never waited for. */
|
||||
static void test_hw_retirement(void)
|
||||
{
|
||||
const struct retro_hw_render_interface *base = NULL;
|
||||
const struct retro_hw_render_interface_rsx_v2 *iface;
|
||||
const struct retro_hw_render_interface_rsx *iface;
|
||||
video_frame_info_t info;
|
||||
rsx_t *rsx;
|
||||
void *memory;
|
||||
unsigned live, finishes;
|
||||
memset(&info, 0, sizeof(info));
|
||||
fake_hwr.context_type = RETRO_HW_CONTEXT_RSX;
|
||||
fake_hwr.version_major = 2;
|
||||
rsx = driver_up();
|
||||
CHECK(rsx_get_hw_render_interface(rsx, &base), "hw_retirement: v2 available");
|
||||
iface = (const struct retro_hw_render_interface_rsx_v2*)base;
|
||||
CHECK(iface->base.interface_version == 2 && iface->retire_memory,
|
||||
CHECK(rsx_get_hw_render_interface(rsx, &base),
|
||||
"hw_retirement: interface available");
|
||||
iface = (const struct retro_hw_render_interface_rsx*)base;
|
||||
CHECK(iface->retire_memory != NULL,
|
||||
"hw_retirement: retirement callback advertised");
|
||||
memory = rsxMemalign(128, 128);
|
||||
live = rsx_live();
|
||||
memory = rsxMemalign(128, 128);
|
||||
live = rsx_live();
|
||||
finishes = rsx_finish_calls;
|
||||
fake_defer_backend = true;
|
||||
CHECK(iface->retire_memory(iface->base.handle, memory),
|
||||
CHECK(iface->retire_memory(iface->handle, memory),
|
||||
"hw_retirement: allocation ownership transferred");
|
||||
rsx_frame(rsx, NULL, 0, 0, 0, NULL, &info);
|
||||
rsx_collect_retired_memory();
|
||||
CHECK(rsx_live() == live && rsx_finish_calls == finishes,
|
||||
"hw_retirement: pending GPU memory preserved without waiting");
|
||||
free(rsx->white_texture);
|
||||
free(rsx);
|
||||
CHECK(rsx_retired_memory_count == 1, "hw_retirement: survives driver teardown");
|
||||
CHECK(rsx_retired_memory_tail - rsx_retired_memory_head == 1,
|
||||
"hw_retirement: survives driver teardown");
|
||||
fake_labels[RSX_RETIRED_MEMORY_LABEL] = rsx_retired_memory_serial;
|
||||
rsx_collect_retired_memory();
|
||||
CHECK(rsx_retired_memory_count == 0, "hw_retirement: completed allocation freed");
|
||||
CHECK(rsx_retired_memory_tail == rsx_retired_memory_head,
|
||||
"hw_retirement: completed allocation freed");
|
||||
rsx_release_all();
|
||||
fake_defer_backend = false;
|
||||
fake_hwr.context_type = RETRO_HW_CONTEXT_NONE;
|
||||
fake_hwr.version_major = 0;
|
||||
printf("hw_retirement: ok\n");
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user