Как реализовать двойную буферизацию в PS2SDK?
Я начал работать в PS2SDK, который является не чем иным, как SDK для PlayStation 2. Я создал простое приложение, основанное на примере куба, которое рисует кубы 20x20. а затем появилась проблема мерцания. Я прочитал, что это может быть решено двойной буферизацией, потому что буфер просто не поспевает за рисованием перед обновлением экрана. Я знаю о решениях двойной буферизации в OpenGL и DirectX, но эта платформа настолько специфична, что я не знаю, как заставить ее работать в моем случае. Я также не нашел ничего о двойной буферизации в PS2SDK.
Вот мой код функции рендеринга (я знаю, что он неоптимизирован и уродлив, но это всего лишь тестирование):
int render(framebuffer_t *frame, zbuffer_t *z)
{
float rotx = 4.71;
float roty = 0;
float posx = -200;
float posy = 25;
float posz = 200;
int k = 0;
int i;
int context = 0;
packet_t *packets[2];
packet_t *current;
qword_t *q;
u64 *dw;
MATRIX local_world;
MATRIX world_view;
MATRIX view_screen;
MATRIX local_screen;
prim_t prim;
color_t color;
VECTOR *temp_vertices;
xyz_t *xyz;
color_t *rgbaq;
texel_t *st;
xyz = memalign(1280, sizeof(u64) * vertex_count);
st = memalign(1280, sizeof(u64) * vertex_count);
temp_vertices = memalign(1280, sizeof(VECTOR) * vertex_count);
packets[0] = packet_init(1000,PACKET_NORMAL);
packets[1] = packet_init(1000,PACKET_NORMAL);
// Define the triangle primitive we want to use.
prim.type = PRIM_TRIANGLE;
prim.shading = PRIM_SHADE_GOURAUD;
prim.mapping = DRAW_ENABLE;
prim.fogging = DRAW_DISABLE;
prim.blending = DRAW_ENABLE;
prim.antialiasing = DRAW_DISABLE;
prim.mapping_type = PRIM_MAP_ST;
prim.colorfix = PRIM_UNFIXED;
color.r = 0x80;
color.g = 0x80;
color.b = 0x80;
color.a = 0x80;
color.q = 1.0f;
// Create the view_screen matrix.
create_view_screen(view_screen, graph_aspect_ratio(), -3.00f, 3.00f, -3.00f, 3.00f, 1.00f, 2000.00f);
// The main loop...
for (;;)
{
VECTOR camera_rotation = { roty, rotx, 0.00f, 1.00f };
VECTOR camera_position = { posx, posy, posz, 1.00f };
int iz;
int ix;
for(iz = 0; iz < 400; iz+=20)
{
for(ix = 0; ix < 400; ix+=20)
{
current = packets[context];
q = current->data;
if(ix == 0 && iz == 0)
{
q = draw_disable_tests(q,0,z);
q = draw_clear(q,0,2048.0f-320.0f,2048.0f-256.0f,frame->width,frame->height,0x40,0x40,0x40);
q = draw_enable_tests(q,0,z);
}
VECTOR object_positionq = { ix, 0.00f, iz, 1.00f };
// Create the local_world matrix.
create_local_world(local_world, object_positionq, object_rotation);
// Create the world_view matrix.
create_world_view(world_view, camera_position, camera_rotation);
// Create the local_screen matrix.
create_local_screen(local_screen, local_world, world_view, view_screen);
// Calculate the vertex values.
calculate_vertices(temp_vertices, vertex_count, vertices, local_screen);
// Generate the XYZ register values.
draw_convert_xyz(xyz, 2048, 2048, 32, vertex_count, (vertex_f_t*)temp_vertices);
// Convert floating point colours to fixed point.
draw_convert_rgbq(rgbaq, vertex_count, (vertex_f_t*)temp_vertices, (color_f_t*)colours,color.a);
// Generate the ST register values.
draw_convert_st(st, vertex_count, (vertex_f_t*)temp_vertices, (texel_f_t*)coordinates);
// Clear framebuffer but don't update zbuffer.
// Draw the triangles using triangle primitive type.
// Use a 64-bit pointer to simplify adding data to the packet.
dw = (u64*)draw_prim_start(q,0,&prim, &color);
for(i = 0; i < points_count; i++)
{
*dw++ = rgbaq[points[i]].rgbaq;
*dw++ = st[points[i]].uv;
*dw++ = xyz[points[i]].xyz;
}
// Only 3 registers rgbaq/st/xyz were used (standard STQ reglist)
q = draw_prim_end((qword_t*)dw,3,DRAW_STQ_REGLIST);
//}
// Setup a finish event.
q = draw_finish(q);
// Now send our current dma chain.
dma_wait_fast();
dma_channel_send_normal(DMA_CHANNEL_GIF,current->data, q - current->data, 0, 0);
context ^= 1;
// Wait for scene to finish drawing
draw_wait_finish();
}
}
free(packets[0]);
free(packets[1]);
graph_wait_vsync();
[...]
Есть ли кто-нибудь, кто понимает этот код SDK достаточно, чтобы дать мне подсказку, как заставить работать двойную буферизацию?