[host] dxgi: finish downsample support for d3d11 backend

This commit is contained in:
Geoffrey McRae 2022-05-03 12:15:24 +10:00
parent 947325e00d
commit 2eec459b47
3 changed files with 114 additions and 40 deletions

View File

@ -61,21 +61,11 @@ static bool d3d11_create(struct DXGIInterface * intf)
this->avgMapTime = runningavg_new(10);
const bool downsample =
dxgi->targetWidth == dxgi->width / 2 &&
dxgi->targetHeight == dxgi->height / 2;
if (!downsample)
{
dxgi->targetWidth = dxgi->width;
dxgi->targetHeight = dxgi->height;
}
D3D11_TEXTURE2D_DESC gpuTexDesc =
{
.Width = dxgi->width,
.Height = dxgi->height,
.MipLevels = 2,
.MipLevels = dxgi->downsampleLevel + 1,
.ArraySize = 1,
.SampleDesc.Count = 1,
.SampleDesc.Quality = 0,
@ -121,7 +111,7 @@ static bool d3d11_create(struct DXGIInterface * intf)
goto fail;
}
if (!downsample)
if (!dxgi->downsampleLevel)
continue;
status = ID3D11Device_CreateTexture2D(dxgi->device, &gpuTexDesc, NULL,
@ -216,15 +206,15 @@ static bool d3d11_copyFrame(Texture * tex, ID3D11Texture2D * src)
FrameDamageRect * rect = tex->texDamageRects + i;
D3D11_BOX box =
{
.left = rect->x,
.top = rect->y,
.left = rect->x << dxgi->downsampleLevel,
.top = rect->y << dxgi->downsampleLevel,
.front = 0,
.back = 1,
.right = rect->x + rect->width,
.bottom = rect->y + rect->height,
.right = (rect->x + rect->width ) << dxgi->downsampleLevel,
.bottom = (rect->y + rect->height) << dxgi->downsampleLevel,
};
ID3D11DeviceContext_CopySubresourceRegion(dxgi->deviceContext,
(ID3D11Resource *)dst, 0, rect->x, rect->y, 0,
(ID3D11Resource *)dst, 0, box.left, box.top, 0,
(ID3D11Resource *)src, 0, &box);
}
}
@ -232,11 +222,10 @@ static bool d3d11_copyFrame(Texture * tex, ID3D11Texture2D * src)
if (teximpl->gpu)
{
ID3D11DeviceContext_GenerateMips(dxgi->deviceContext, teximpl->srv);
if (tex->texDamageCount < 0)
ID3D11DeviceContext_CopySubresourceRegion(dxgi->deviceContext,
(ID3D11Resource *)teximpl->cpu, 0, 0, 0, 0,
(ID3D11Resource *)dst , 1, NULL);
(ID3D11Resource *)dst , dxgi->downsampleLevel, NULL);
else
{
for (int i = 0; i < tex->texDamageCount; ++i)
@ -244,17 +233,17 @@ static bool d3d11_copyFrame(Texture * tex, ID3D11Texture2D * src)
FrameDamageRect * rect = tex->texDamageRects + i;
D3D11_BOX box =
{
.left = rect->x / 2,
.top = rect->y / 2,
.left = rect->x,
.top = rect->y,
.front = 0,
.back = 1,
.right = (rect->x + rect->width ) / 2,
.bottom = (rect->y + rect->height) / 2,
.right = rect->x + rect->width ,
.bottom = rect->y + rect->height,
};
ID3D11DeviceContext_CopySubresourceRegion(dxgi->deviceContext,
(ID3D11Resource *)teximpl->cpu, 0, rect->x / 2, rect->y / 2, 0,
(ID3D11Resource *)dst , 1, &box);
(ID3D11Resource *)teximpl->cpu, 0, box.left, box.top, 0,
(ID3D11Resource *)dst , dxgi->downsampleLevel, &box);
}
}
}

View File

@ -29,6 +29,7 @@
#include "common/rects.h"
#include "common/runningavg.h"
#include "common/KVMFR.h"
#include "common/vector.h"
#include <stdatomic.h>
#include <unistd.h>
@ -45,6 +46,18 @@
#define LOCKED(...) INTERLOCKED_SECTION(this->deviceContextLock, __VA_ARGS__)
typedef struct
{
unsigned int id;
bool greater;
unsigned int x;
unsigned int y;
unsigned int level;
}
DownsampleRule;
static Vector downsampleRules = {0};
// locals
static struct DXGIInterface * this = NULL;
@ -73,6 +86,58 @@ static const char * dxgi_getName(void)
return name;
}
static bool downsampleOptParser(struct Option * opt, const char * str)
{
if (!str)
return false;
opt->value.x_string = strdup(str);
if (downsampleRules.data)
vector_destroy(&downsampleRules);
if (!vector_create(&downsampleRules, sizeof(DownsampleRule), 10))
{
DEBUG_ERROR("Failed to allocate ram");
return false;
}
char * tmp = strdup(str);
char * token = strtok(tmp, ",");
int count = 0;
while(token)
{
DownsampleRule rule = {0};
if (token[0] == '>')
{
rule.greater = true;
++token;
}
if (sscanf(token, "%ux%u:%u", &rule.x, &rule.y, &rule.level) != 3)
return false;
rule.id = count++;
DEBUG_INFO(
"Rule %u: %u%% IF X %s %4u %s Y %s %4u",
rule.id,
100 / (1 << rule.level),
rule.greater ? "> " : "==",
rule.x,
rule.greater ? "OR " : "AND",
rule.greater ? "> " : "==",
rule.y
);
vector_push(&downsampleRules, &rule);
token = strtok(NULL, ",");
}
free(tmp);
return true;
}
static void dxgi_initOptions(void)
{
struct Option options[] =
@ -91,6 +156,14 @@ static void dxgi_initOptions(void)
.type = OPTION_TYPE_STRING,
.value.x_string = NULL
},
{
.module = "dxgi",
.name = "downsample", //dxgi:downsample=1920x1200:1,
.description = "Downsample conditions and levels, format: [>](width)x(height):level",
.type = OPTION_TYPE_STRING,
.value.x_string = NULL,
.parser = downsampleOptParser
},
{
.module = "dxgi",
.name = "maxTextures",
@ -390,16 +463,6 @@ static bool dxgi_init(void)
break;
}
this->targetWidth = this->width;
this->targetHeight = this->height;
//TODO: add logic here
if (this->width > 1920 && this->height > 1200)
{
this->targetWidth /= 2;
this->targetHeight /= 2;
}
switch(outputDesc.Rotation)
{
case DXGI_MODE_ROTATION_ROTATE90:
@ -423,7 +486,6 @@ static bool dxgi_init(void)
DEBUG_INFO("Feature Level : 0x%x" , this->featureLevel);
DEBUG_INFO("Capture Size : %u x %u", this->width, this->height);
DEBUG_INFO("Target Size : %u x %u", this->targetWidth, this->targetHeight);
DEBUG_INFO("AcquireLock : %s" , this->useAcquireLock ? "enabled" : "disabled");
DEBUG_INFO("Debug mode : %s" , this->debug ? "enabled" : "disabled");
@ -536,6 +598,26 @@ static bool dxgi_init(void)
goto fail;
}
this->targetWidth = this->width;
this->targetHeight = this->height;
DownsampleRule * rule;
vector_forEachRef(rule, &downsampleRules)
{
if (
( rule->greater && (this->width > rule->x || this->height > rule->y)) ||
(!rule->greater && (this->width == rule->x && this->height == rule->y)))
{
DEBUG_INFO("Matched downsample rule %d", rule->id);
this->downsampleLevel = rule->level;
this->targetWidth >>= rule->level;
this->targetHeight >>= rule->level;
break;
}
}
DEBUG_INFO("Request Size : %u x %u", this->targetWidth, this->targetHeight);
const char * copyBackend = option_get_string("dxgi", "copyBackend");
for (int i = 0; i < ARRAY_LENGTH(backends); ++i)
{
@ -552,6 +634,8 @@ static bool dxgi_init(void)
}
}
DEBUG_INFO("Output Size : %u x %u", this->targetWidth, this->targetHeight);
if (!this->backend)
{
DEBUG_ERROR("Could not find copy backend: %s", copyBackend);
@ -699,10 +783,10 @@ static void rectToFrameDamageRect(RECT * src, FrameDamageRect * dst)
{
*dst = (FrameDamageRect)
{
.x = src->left,
.y = src->top,
.width = src->right - src->left,
.height = src->bottom - src->top
.x = src->left >> this->downsampleLevel,
.y = src->top >> this->downsampleLevel,
.width = (src->right - src->left) >> this->downsampleLevel,
.height = (src->bottom - src->top) >> this->downsampleLevel
};
}

View File

@ -95,6 +95,7 @@ struct DXGIInterface
unsigned int formatVer;
unsigned int width , targetWidth ;
unsigned int height, targetHeight;
unsigned int downsampleLevel;
unsigned int pitch;
unsigned int stride;
unsigned int bpp;