1
0
mirror of https://github.com/Yours3lf/rpi-vk-driver.git synced 2025-01-19 11:52:16 +01:00

initial vsync implementation done

This commit is contained in:
yours3lf 2020-06-02 22:06:55 +01:00
parent f763dc1e6d
commit 5c4dc59395
5 changed files with 158 additions and 34 deletions

View File

@ -64,10 +64,35 @@ uint32_t fifoAdd(Fifo* f, void* data)
return 1; return 1;
} }
void fifoRemove(Fifo* f, void* data) void* fifoGetLast(Fifo* f)
{ {
assert(f); assert(f);
if(f->last)
{
return f->last->data;
}
return 0;
}
void* fifoGetFirst(Fifo* f)
{
assert(f);
if(f->first)
{
return f->first->data;
}
return 0;
}
uint32_t fifoRemove(Fifo* f, void* data)
{
assert(f);
assert(data);
if(f->last) if(f->last)
{ {
memcpy(data, f->last->data, f->dataSize); memcpy(data, f->last->data, f->dataSize);
@ -87,7 +112,11 @@ void fifoRemove(Fifo* f, void* data)
poolFree(&f->dataBuf, tmp->data); poolFree(&f->dataBuf, tmp->data);
poolFree(&f->fifoElemBuf, tmp); poolFree(&f->fifoElemBuf, tmp);
return 1;
} }
return 0;
} }
void debugPrintFifo(Fifo* f) void debugPrintFifo(Fifo* f)

View File

@ -30,7 +30,9 @@ typedef struct Fifo
Fifo createFifo(void* dataMem, void* fifoElemMem, uint32_t maxElems, uint32_t dataSize); Fifo createFifo(void* dataMem, void* fifoElemMem, uint32_t maxElems, uint32_t dataSize);
void destroyFifo(Fifo* f); void destroyFifo(Fifo* f);
uint32_t fifoAdd(Fifo* f, void* data); uint32_t fifoAdd(Fifo* f, void* data);
void fifoRemove(Fifo* f, void* data); uint32_t fifoRemove(Fifo* f, void* data);
void* fifoGetLast(Fifo* f);
void* fifoGetFirst(Fifo* f);
void debugPrintFifo(Fifo* f); void debugPrintFifo(Fifo* f);
#if defined (__cplusplus) #if defined (__cplusplus)

View File

@ -1,8 +1,22 @@
#include "modeset.h" #include "modeset.h"
#include "fifo.h"
#include <stdatomic.h> #include <stdatomic.h>
atomic_int saved_state_guard = 0; atomic_int saved_state_guard = 0;
typedef struct vsyncData
{
_image* i;
modeset_display_surface* s;
uint32_t pending;
} vsyncData;
static Fifo flipQueueFifo = {};
static vsyncData dataMem[5];
static FifoElem fifoMem[5];
atomic_int flip_queue_guard = 0;
void modeset_enum_displays(int fd, uint32_t* numDisplays, modeset_display* displays) void modeset_enum_displays(int fd, uint32_t* numDisplays, modeset_display* displays)
{ {
drmModeResPtr resPtr = drmModeGetResources(fd); drmModeResPtr resPtr = drmModeGetResources(fd);
@ -166,6 +180,16 @@ void modeset_create_surface_for_mode(int fd, uint32_t display, uint32_t mode, mo
{ {
// modeset_debug_print(fd); // modeset_debug_print(fd);
while(flip_queue_guard);
flip_queue_guard = 1;
if(!flipQueueFifo.maxElems)
{
flipQueueFifo = createFifo(dataMem, fifoMem, 5, sizeof(vsyncData));
}
flip_queue_guard = 0;
surface->savedState = 0; surface->savedState = 0;
drmModeResPtr resPtr = drmModeGetResources(fd); drmModeResPtr resPtr = drmModeGetResources(fd);
@ -253,49 +277,85 @@ void modeset_destroy_fb(int fd, _image* buf)
drmModeRmFB(fd, buf->fb); drmModeRmFB(fd, buf->fb);
} }
typedef struct vsyncData
{
_image* i;
modeset_display_surface* s;
uint32_t pending;
} vsyncData;
static vsyncData flipQueue[2] = {};
atomic_int flip_queue_guard = 0;
static void modeset_page_flip_event(int fd, unsigned int frame, static void modeset_page_flip_event(int fd, unsigned int frame,
unsigned int sec, unsigned int usec, unsigned int sec, unsigned int usec,
void *data) void *data)
{ {
if(data) if(data)
{ {
vsyncData* d = data;
while(flip_queue_guard); while(flip_queue_guard);
flip_queue_guard = 1; flip_queue_guard = 1;
flipQueue[0].pending = 0; if(data)
{
vsyncData* d = data;
d->pending = 0;
}
flip_queue_guard = 0; flip_queue_guard = 0;
} }
} }
void modeset_acquire_image(int fd, _image* buf, modeset_display_surface* surface) void modeset_acquire_image(int fd, _image** buf, modeset_display_surface** surface)
{ {
uint32_t pending = 1;
while(flip_queue_guard); while(flip_queue_guard);
flip_queue_guard = 1; flip_queue_guard = 1;
//TODO vsyncData* last = fifoGetLast(&flipQueueFifo);
//try to find any image that's not pending
//call handle event until that happens if(last)
//then find a non-pending image {
drmEventContext ev; pending = last->pending;
memset(&ev, 0, sizeof(ev)); }
ev.version = 2; else
ev.page_flip_handler = modeset_page_flip_event; {
drmHandleEvent(fd, &ev); //fifo empty, just use any image
*buf = 0;
*surface = 0;
flip_queue_guard = 0;
return;
}
flip_queue_guard = 0; flip_queue_guard = 0;
while(pending)
{
drmEventContext ev;
memset(&ev, 0, sizeof(ev));
ev.version = 2;
ev.page_flip_handler = modeset_page_flip_event;
drmHandleEvent(fd, &ev);
while(flip_queue_guard);
flip_queue_guard = 1;
vsyncData* d = fifoGetLast(&flipQueueFifo);
//a frame must be in flight
//so fifo must contain something
assert(d);
pending = d->pending;
flip_queue_guard = 0;
}
vsyncData d;
while(flip_queue_guard);
flip_queue_guard = 1;
fifoRemove(&flipQueueFifo, &d);
flip_queue_guard = 0;
*buf = d.i;
*surface = d.s;
} }
void modeset_present(int fd, _image *buf, modeset_display_surface* surface) void modeset_present(int fd, _image *buf, modeset_display_surface* surface)
@ -342,16 +402,29 @@ void modeset_present(int fd, _image *buf, modeset_display_surface* surface)
d.s = surface; d.s = surface;
d.pending = 1; d.pending = 1;
while(flipQueue[0].pending); uint32_t added = 0;
while(!added)
{
while(flip_queue_guard);
flip_queue_guard = 1;
//try to add request to queue
added = fifoAdd(&flipQueueFifo, &d);
flip_queue_guard = 0;
}
void* first = 0;
while(flip_queue_guard); while(flip_queue_guard);
flip_queue_guard = 1; flip_queue_guard = 1;
flipQueue[0] = d; first = fifoGetFirst(&flipQueueFifo);
drmModePageFlip(fd, surface->crtc->crtc_id, buf->fb, DRM_MODE_PAGE_FLIP_EVENT, &flipQueue[0]);
flip_queue_guard = 0; flip_queue_guard = 0;
drmModePageFlip(fd, surface->crtc->crtc_id, buf->fb, DRM_MODE_PAGE_FLIP_EVENT, first);
} }
//modeset_debug_print(fd); //modeset_debug_print(fd);

View File

@ -62,7 +62,7 @@ void modeset_create_surface_for_mode(int fd, uint32_t display, uint32_t mode, mo
void modeset_create_fb_for_surface(int fd, _image* buf, modeset_display_surface* surface); void modeset_create_fb_for_surface(int fd, _image* buf, modeset_display_surface* surface);
void modeset_destroy_fb(int fd, _image* buf); void modeset_destroy_fb(int fd, _image* buf);
void modeset_present(int fd, _image* buf, modeset_display_surface* surface); void modeset_present(int fd, _image* buf, modeset_display_surface* surface);
void modeset_acquire_image(int fd, _image* buf, modeset_display_surface* surface); void modeset_acquire_image(int fd, _image** buf, modeset_display_surface** surface);
void modeset_destroy_surface(int fd, modeset_display_surface* surface); void modeset_destroy_surface(int fd, modeset_display_surface* surface);
void modeset_debug_print(int fd); void modeset_debug_print(int fd);

View File

@ -466,17 +466,38 @@ VKAPI_ATTR VkResult VKAPI_CALL RPIFUNC(vkAcquireNextImageKHR)(
assert(semaphore != VK_NULL_HANDLE || fence != VK_NULL_HANDLE); assert(semaphore != VK_NULL_HANDLE || fence != VK_NULL_HANDLE);
sem_t* s = semaphore; sem_t* sem = semaphore;
_swapchain* sc = swapchain;
//TODO we need to keep track of currently acquired images? //TODO we need to keep track of currently acquired images?
//TODO wait timeout? //TODO wait timeout?
*pImageIndex = ((_swapchain*)swapchain)->backbufferIdx; //return back buffer index _image* i;
modeset_display_surface* surf;
modeset_acquire_image(controlFd, &i, &surf);
if(i && surf)
{
for(uint32_t c = 0; c < sc->numImages; ++c)
{
if(&sc->images[c] == i && sc->surface == surf)
{
sc->backbufferIdx = c;
break;
}
}
}
else
{
sc->backbufferIdx = 0;
}
*pImageIndex = sc->backbufferIdx; //return back buffer index
//signal semaphore //signal semaphore
int semVal; sem_getvalue(s, &semVal); assert(semVal <= 0); //make sure semaphore is unsignalled int semVal; sem_getvalue(sem, &semVal); assert(semVal <= 0); //make sure semaphore is unsignalled
sem_post(s); sem_post(sem);
_fence* f = fence; _fence* f = fence;
if(f) if(f)
@ -526,7 +547,6 @@ VKAPI_ATTR VkResult VKAPI_CALL RPIFUNC(vkQueuePresentKHR)(
{ {
_swapchain* s = pPresentInfo->pSwapchains[c]; _swapchain* s = pPresentInfo->pSwapchains[c];
modeset_present(controlFd, &s->images[pPresentInfo->pImageIndices[c]], s->surface); modeset_present(controlFd, &s->images[pPresentInfo->pImageIndices[c]], s->surface);
s->backbufferIdx = (pPresentInfo->pImageIndices[c] + 1) % s->numImages;
} }
PROFILEEND(RPIFUNC(vkQueuePresentKHR)); PROFILEEND(RPIFUNC(vkQueuePresentKHR));