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

View File

@ -29,6 +29,7 @@
#include "common/rects.h" #include "common/rects.h"
#include "common/runningavg.h" #include "common/runningavg.h"
#include "common/KVMFR.h" #include "common/KVMFR.h"
#include "common/vector.h"
#include <stdatomic.h> #include <stdatomic.h>
#include <unistd.h> #include <unistd.h>
@ -45,6 +46,18 @@
#define LOCKED(...) INTERLOCKED_SECTION(this->deviceContextLock, __VA_ARGS__) #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 // locals
static struct DXGIInterface * this = NULL; static struct DXGIInterface * this = NULL;
@ -73,6 +86,58 @@ static const char * dxgi_getName(void)
return name; 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) static void dxgi_initOptions(void)
{ {
struct Option options[] = struct Option options[] =
@ -91,6 +156,14 @@ static void dxgi_initOptions(void)
.type = OPTION_TYPE_STRING, .type = OPTION_TYPE_STRING,
.value.x_string = NULL .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", .module = "dxgi",
.name = "maxTextures", .name = "maxTextures",
@ -390,16 +463,6 @@ static bool dxgi_init(void)
break; 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) switch(outputDesc.Rotation)
{ {
case DXGI_MODE_ROTATION_ROTATE90: case DXGI_MODE_ROTATION_ROTATE90:
@ -423,7 +486,6 @@ static bool dxgi_init(void)
DEBUG_INFO("Feature Level : 0x%x" , this->featureLevel); DEBUG_INFO("Feature Level : 0x%x" , this->featureLevel);
DEBUG_INFO("Capture Size : %u x %u", this->width, this->height); 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("AcquireLock : %s" , this->useAcquireLock ? "enabled" : "disabled");
DEBUG_INFO("Debug mode : %s" , this->debug ? "enabled" : "disabled"); DEBUG_INFO("Debug mode : %s" , this->debug ? "enabled" : "disabled");
@ -536,6 +598,26 @@ static bool dxgi_init(void)
goto fail; 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"); const char * copyBackend = option_get_string("dxgi", "copyBackend");
for (int i = 0; i < ARRAY_LENGTH(backends); ++i) 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) if (!this->backend)
{ {
DEBUG_ERROR("Could not find copy backend: %s", copyBackend); DEBUG_ERROR("Could not find copy backend: %s", copyBackend);
@ -699,10 +783,10 @@ static void rectToFrameDamageRect(RECT * src, FrameDamageRect * dst)
{ {
*dst = (FrameDamageRect) *dst = (FrameDamageRect)
{ {
.x = src->left, .x = src->left >> this->downsampleLevel,
.y = src->top, .y = src->top >> this->downsampleLevel,
.width = src->right - src->left, .width = (src->right - src->left) >> this->downsampleLevel,
.height = src->bottom - src->top .height = (src->bottom - src->top) >> this->downsampleLevel
}; };
} }

View File

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