mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-25 14:57:20 +00:00
[host] dxgi: sleep until it's close to time to map
This change adds an average function to time how long it takes the GPU to copy and map the texture, and then uses this average to sleep for 80% of this average lowering CPU usage and potentially decreasing lock contention.
This commit is contained in:
parent
7f5f46c448
commit
f02d61d665
@ -28,6 +28,7 @@ set(COMMON_SOURCES
|
|||||||
src/framebuffer.c
|
src/framebuffer.c
|
||||||
src/KVMFR.c
|
src/KVMFR.c
|
||||||
src/countedbuffer.c
|
src/countedbuffer.c
|
||||||
|
src/runningavg.c
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(lg_common STATIC ${COMMON_SOURCES})
|
add_library(lg_common STATIC ${COMMON_SOURCES})
|
||||||
|
28
common/include/common/runningavg.h
Normal file
28
common/include/common/runningavg.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
Looking Glass
|
||||||
|
Copyright (C) 2017-2021 The Looking Glass Authors
|
||||||
|
https://looking-glass.io
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 2 of the License, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||||
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct RunningAvg * RunningAvg;
|
||||||
|
|
||||||
|
RunningAvg runningavg_new(int length);
|
||||||
|
void runningavg_free(RunningAvg * ra);
|
||||||
|
void runningavg_push(RunningAvg ra, int64_t value);
|
||||||
|
void runningavg_reset(RunningAvg ra);
|
||||||
|
double runningavg_calc(RunningAvg ra);
|
69
common/src/runningavg.c
Normal file
69
common/src/runningavg.c
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
Looking Glass
|
||||||
|
Copyright (C) 2017-2021 The Looking Glass Authors
|
||||||
|
https://looking-glass.io
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 2 of the License, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||||
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common/runningavg.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
struct RunningAvg
|
||||||
|
{
|
||||||
|
int length, samples;
|
||||||
|
int pos;
|
||||||
|
int value;
|
||||||
|
int64_t values[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
RunningAvg runningavg_new(int length)
|
||||||
|
{
|
||||||
|
struct RunningAvg * ra = calloc(1, sizeof(*ra) + sizeof(*ra->values) * length);
|
||||||
|
ra->length = length;
|
||||||
|
return ra;
|
||||||
|
}
|
||||||
|
|
||||||
|
void runningavg_free(RunningAvg * ra)
|
||||||
|
{
|
||||||
|
free(*ra);
|
||||||
|
*ra = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void runningavg_push(RunningAvg ra, int64_t value)
|
||||||
|
{
|
||||||
|
if (ra->samples == ra->length)
|
||||||
|
ra->value -= ra->values[ra->pos];
|
||||||
|
else
|
||||||
|
++ra->samples;
|
||||||
|
|
||||||
|
ra->value += value;
|
||||||
|
ra->values[ra->pos++] = value;
|
||||||
|
|
||||||
|
if (ra->pos == ra->length)
|
||||||
|
ra->pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void runningavg_reset(RunningAvg ra)
|
||||||
|
{
|
||||||
|
ra->samples = 0;
|
||||||
|
ra->pos = 0;
|
||||||
|
ra->value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double runningavg_calc(RunningAvg ra)
|
||||||
|
{
|
||||||
|
return (double)ra->value / ra->samples;
|
||||||
|
}
|
@ -26,6 +26,7 @@
|
|||||||
#include "common/locking.h"
|
#include "common/locking.h"
|
||||||
#include "common/event.h"
|
#include "common/event.h"
|
||||||
#include "common/dpi.h"
|
#include "common/dpi.h"
|
||||||
|
#include "common/runningavg.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
@ -63,6 +64,7 @@ typedef struct Texture
|
|||||||
volatile enum TextureState state;
|
volatile enum TextureState state;
|
||||||
ID3D11Texture2D * tex;
|
ID3D11Texture2D * tex;
|
||||||
D3D11_MAPPED_SUBRESOURCE map;
|
D3D11_MAPPED_SUBRESOURCE map;
|
||||||
|
uint64_t copyTime;
|
||||||
}
|
}
|
||||||
Texture;
|
Texture;
|
||||||
|
|
||||||
@ -90,6 +92,9 @@ struct iface
|
|||||||
atomic_int texReady;
|
atomic_int texReady;
|
||||||
bool needsRelease;
|
bool needsRelease;
|
||||||
|
|
||||||
|
RunningAvg avgMapTime;
|
||||||
|
uint64_t usleepMapTime;
|
||||||
|
|
||||||
CaptureGetPointerBuffer getPointerBufferFn;
|
CaptureGetPointerBuffer getPointerBufferFn;
|
||||||
CapturePostPointerBuffer postPointerBufferFn;
|
CapturePostPointerBuffer postPointerBufferFn;
|
||||||
LGEvent * frameEvent;
|
LGEvent * frameEvent;
|
||||||
@ -185,6 +190,7 @@ static bool dxgi_create(CaptureGetPointerBuffer getPointerBufferFn, CapturePostP
|
|||||||
this->texture = calloc(sizeof(struct Texture), this->maxTextures);
|
this->texture = calloc(sizeof(struct Texture), this->maxTextures);
|
||||||
this->getPointerBufferFn = getPointerBufferFn;
|
this->getPointerBufferFn = getPointerBufferFn;
|
||||||
this->postPointerBufferFn = postPointerBufferFn;
|
this->postPointerBufferFn = postPointerBufferFn;
|
||||||
|
this->avgMapTime = runningavg_new(10);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,6 +227,9 @@ static bool dxgi_init(void)
|
|||||||
this->texWIndex = 0;
|
this->texWIndex = 0;
|
||||||
atomic_store(&this->texReady, 0);
|
atomic_store(&this->texReady, 0);
|
||||||
|
|
||||||
|
runningavg_reset(this->avgMapTime);
|
||||||
|
this->usleepMapTime = 0;
|
||||||
|
|
||||||
lgResetEvent(this->frameEvent);
|
lgResetEvent(this->frameEvent);
|
||||||
|
|
||||||
status = CreateDXGIFactory1(&IID_IDXGIFactory1, (void **)&this->factory);
|
status = CreateDXGIFactory1(&IID_IDXGIFactory1, (void **)&this->factory);
|
||||||
@ -700,6 +709,7 @@ static void dxgi_free(void)
|
|||||||
|
|
||||||
free(this->texture);
|
free(this->texture);
|
||||||
|
|
||||||
|
runningavg_free(&this->avgMapTime);
|
||||||
free(this);
|
free(this);
|
||||||
this = NULL;
|
this = NULL;
|
||||||
}
|
}
|
||||||
@ -821,6 +831,7 @@ static CaptureResult dxgi_capture(void)
|
|||||||
if (copyFrame)
|
if (copyFrame)
|
||||||
{
|
{
|
||||||
// issue the copy from GPU to CPU RAM
|
// issue the copy from GPU to CPU RAM
|
||||||
|
tex->copyTime = microtime();
|
||||||
ID3D11DeviceContext_CopyResource(this->deviceContext,
|
ID3D11DeviceContext_CopyResource(this->deviceContext,
|
||||||
(ID3D11Resource *)tex->tex, (ID3D11Resource *)src);
|
(ID3D11Resource *)tex->tex, (ID3D11Resource *)src);
|
||||||
}
|
}
|
||||||
@ -935,6 +946,11 @@ static CaptureResult dxgi_waitFrame(CaptureFrame * frame)
|
|||||||
|
|
||||||
Texture * tex = &this->texture[this->texRIndex];
|
Texture * tex = &this->texture[this->texRIndex];
|
||||||
|
|
||||||
|
// sleep until it's close to time to map
|
||||||
|
const uint64_t delta = microtime() - tex->copyTime;
|
||||||
|
if (delta < this->usleepMapTime)
|
||||||
|
usleep(this->usleepMapTime - delta);
|
||||||
|
|
||||||
// try to map the resource, but don't wait for it
|
// try to map the resource, but don't wait for it
|
||||||
for (int i = 0; ; ++i)
|
for (int i = 0; ; ++i)
|
||||||
{
|
{
|
||||||
@ -958,6 +974,10 @@ static CaptureResult dxgi_waitFrame(CaptureFrame * frame)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update the sleep average and sleep for 80% of the average on the next call
|
||||||
|
runningavg_push(this->avgMapTime, microtime() - tex->copyTime);
|
||||||
|
this->usleepMapTime = (uint64_t)(runningavg_calc(this->avgMapTime) * 0.8);
|
||||||
|
|
||||||
tex->state = TEXTURE_STATE_MAPPED;
|
tex->state = TEXTURE_STATE_MAPPED;
|
||||||
|
|
||||||
frame->formatVer = tex->formatVer;
|
frame->formatVer = tex->formatVer;
|
||||||
|
Loading…
Reference in New Issue
Block a user