[c-host] dxgi: futher event improvements

This commit is contained in:
Geoffrey McRae 2019-12-17 16:36:43 +11:00
parent 9c5f9906fa
commit c82a5e0523
2 changed files with 54 additions and 30 deletions

View File

@ -46,7 +46,6 @@ typedef struct Texture
enum TextureState state; enum TextureState state;
ID3D11Texture2D * tex; ID3D11Texture2D * tex;
D3D11_MAPPED_SUBRESOURCE map; D3D11_MAPPED_SUBRESOURCE map;
osEventHandle * readyEvent;
} }
Texture; Texture;
@ -80,10 +79,12 @@ struct iface
IDXGIOutputDuplication * dup; IDXGIOutputDuplication * dup;
int maxTextures; int maxTextures;
Texture * texture; Texture * texture;
volatile int texRIndex; int texRIndex;
int texWIndex; int texWIndex;
volatile int texReady;
bool needsRelease; bool needsRelease;
osEventHandle * pointerEvent; osEventHandle * pointerEvent;
osEventHandle * frameEvent;
unsigned int width; unsigned int width;
unsigned int height; unsigned int height;
@ -172,27 +173,20 @@ static bool dxgi_create()
return false; return false;
} }
this->frameEvent = os_createEvent(true, 17); // 60Hz = 16.7ms
if (!this->frameEvent)
{
DEBUG_ERROR("failed to create the frame event");
free(this);
return false;
}
this->maxTextures = option_get_int("dxgi", "maxTextures"); this->maxTextures = option_get_int("dxgi", "maxTextures");
if (this->maxTextures <= 0) if (this->maxTextures <= 0)
this->maxTextures = 1; this->maxTextures = 1;
this->texture = calloc(sizeof(struct Texture), this->maxTextures);
for(int i = 0; i < this->maxTextures; ++i)
{
this->texture[i].readyEvent = os_createEvent(false, 30);
if (!this->texture[i].readyEvent)
{
DEBUG_ERROR("failed to create the texture event");
for(int x = 0; x < i; ++x)
os_freeEvent(this->texture[x].readyEvent);
free(this->texture);
free(this);
}
}
this->useAcquireLock = option_get_bool("dxgi", "useAcquireLock"); this->useAcquireLock = option_get_bool("dxgi", "useAcquireLock");
this->texture = calloc(sizeof(struct Texture), this->maxTextures);
return true; return true;
} }
@ -226,6 +220,7 @@ static bool dxgi_init(void * pointerShape, const unsigned int pointerSize)
this->stop = false; this->stop = false;
this->texRIndex = 0; this->texRIndex = 0;
this->texWIndex = 0; this->texWIndex = 0;
this->texReady = 0;
status = CreateDXGIFactory1(&IID_IDXGIFactory1, (void **)&this->factory); status = CreateDXGIFactory1(&IID_IDXGIFactory1, (void **)&this->factory);
if (FAILED(status)) if (FAILED(status))
@ -682,11 +677,12 @@ static CaptureResult dxgi_capture()
ID3D11Texture2D_Release(src); ID3D11Texture2D_Release(src);
// set the state and signal // set the state, and signal
tex->state = TEXTURE_STATE_PENDING_MAP; tex->state = TEXTURE_STATE_PENDING_MAP;
os_signalEvent(tex->readyEvent); INTERLOCKED_INC(&this->texReady);
os_signalEvent(this->frameEvent);
// advance our write pointer // advance the write index
if (++this->texWIndex == this->maxTextures) if (++this->texWIndex == this->maxTextures)
this->texWIndex = 0; this->texWIndex = 0;
@ -760,10 +756,18 @@ static CaptureResult dxgi_waitFrame(CaptureFrame * frame)
assert(this); assert(this);
assert(this->initialized); assert(this->initialized);
Texture * tex = &this->texture[INTERLOCKED_GET(&this->texRIndex)]; // NOTE: the event may be signaled when there are no frames available
if (!os_waitEvent(tex->readyEvent, 1000)) if(this->texReady == 0)
{
if (!os_waitEvent(this->frameEvent, 1000))
return CAPTURE_RESULT_TIMEOUT; return CAPTURE_RESULT_TIMEOUT;
if (this->texReady == 0)
return CAPTURE_RESULT_TIMEOUT;
}
Texture * tex = &this->texture[this->texRIndex];
// try to map the resource, but don't wait for it // try to map the resource, but don't wait for it
HRESULT status; HRESULT status;
LOCKED({status = ID3D11DeviceContext_Map(this->deviceContext, (ID3D11Resource*)tex->tex, 0, D3D11_MAP_READ, 0x100000L, &tex->map);}); LOCKED({status = ID3D11DeviceContext_Map(this->deviceContext, (ID3D11Resource*)tex->tex, 0, D3D11_MAP_READ, 0x100000L, &tex->map);});
@ -784,7 +788,7 @@ static CaptureResult dxgi_waitFrame(CaptureFrame * frame)
frame->stride = this->stride; frame->stride = this->stride;
frame->format = this->format; frame->format = this->format;
os_resetEvent(tex->readyEvent); INTERLOCKED_DEC(&this->texReady);
return CAPTURE_RESULT_OK; return CAPTURE_RESULT_OK;
} }
@ -793,14 +797,14 @@ static CaptureResult dxgi_getFrame(FrameBuffer frame)
assert(this); assert(this);
assert(this->initialized); assert(this->initialized);
Texture * tex = &this->texture[INTERLOCKED_GET(&this->texRIndex)]; Texture * tex = &this->texture[this->texRIndex];
framebuffer_write(frame, tex->map.pData, this->pitch * this->height); framebuffer_write(frame, tex->map.pData, this->pitch * this->height);
LOCKED({ID3D11DeviceContext_Unmap(this->deviceContext, (ID3D11Resource*)tex->tex, 0);}); LOCKED({ID3D11DeviceContext_Unmap(this->deviceContext, (ID3D11Resource*)tex->tex, 0);});
tex->state = TEXTURE_STATE_UNUSED; tex->state = TEXTURE_STATE_UNUSED;
INTERLOCKED_INC(&this->texRIndex); if (++this->texRIndex == this->maxTextures)
INTERLOCKED_CE (&this->texRIndex, this->maxTextures, 0); this->texRIndex = 0;
return CAPTURE_RESULT_OK; return CAPTURE_RESULT_OK;
} }

View File

@ -30,6 +30,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include "interface/platform.h" #include "interface/platform.h"
#include "common/debug.h" #include "common/debug.h"
#include "common/option.h" #include "common/option.h"
#include "common/locking.h"
#include "windows/debug.h" #include "windows/debug.h"
#include "ivshmem.h" #include "ivshmem.h"
@ -72,6 +73,7 @@ struct osThreadHandle
struct osEventHandle struct osEventHandle
{ {
volatile int lock;
bool reset; bool reset;
HANDLE handle; HANDLE handle;
bool wrapped; bool wrapped;
@ -510,10 +512,13 @@ osEventHandle * os_createEvent(bool autoReset, unsigned int msSpinTime)
return NULL; return NULL;
} }
event->lock = 0;
event->reset = autoReset; event->reset = autoReset;
event->handle = CreateEvent(NULL, autoReset ? FALSE : TRUE, FALSE, NULL);
event->wrapped = false; event->wrapped = false;
event->msSpinTime = msSpinTime; event->msSpinTime = msSpinTime;
event->handle = CreateEvent(NULL, autoReset ? FALSE : TRUE, FALSE, NULL); event->signaled = false;
if (!event->handle) if (!event->handle)
{ {
DEBUG_WINERROR("Failed to create the event", GetLastError()); DEBUG_WINERROR("Failed to create the event", GetLastError());
@ -533,10 +538,12 @@ osEventHandle * os_wrapEvent(HANDLE handle)
return NULL; return NULL;
} }
event->lock = 0;
event->reset = false; event->reset = false;
event->handle = event; event->handle = event;
event->wrapped = true; event->wrapped = true;
event->msSpinTime = 0; event->msSpinTime = 0;
event->signaled = false;
return event; return event;
} }
@ -551,10 +558,19 @@ bool os_waitEvent(osEventHandle * event, unsigned int timeout)
if (!event->wrapped) if (!event->wrapped)
{ {
if (event->signaled) if (event->signaled)
{
if (event->reset)
event->signaled = false;
return true; return true;
}
if (timeout == 0) if (timeout == 0)
return event->signaled; {
bool ret = event->signaled;
if (event->reset)
event->signaled = false;
return ret;
}
if (event->msSpinTime) if (event->msSpinTime)
{ {
@ -581,9 +597,13 @@ bool os_waitEvent(osEventHandle * event, unsigned int timeout)
} }
if (event->signaled) if (event->signaled)
{
if (event->reset)
event->signaled = false;
return true; return true;
} }
} }
}
const DWORD to = (timeout == TIMEOUT_INFINITE) ? INFINITE : (DWORD)timeout; const DWORD to = (timeout == TIMEOUT_INFINITE) ? INFINITE : (DWORD)timeout;
while(true) while(true)