Blinue / Magpie

An all-purpose window upscaler for Windows 10/11.
GNU General Public License v3.0
9.12k stars 482 forks source link

Interpolation Frame for performance boost #634

Closed marcos32123 closed 1 year ago

marcos32123 commented 1 year ago

Expected behavior 预期的功能

include

include

include

// Variáveis globais ID3D11Device g_pd3dDevice = nullptr; IDXGIOutputDuplication g_pDesktopDuplication = nullptr; IDXGIOutput1 g_pOutput = nullptr; ID3D11Texture2D g_pAcquiredDesktopImage = nullptr;

// Função para inicialização do DirectX e captura de tela bool InitializeDirectX() { // Criação do dispositivo DirectX 11 D3D_FEATURE_LEVEL featureLevel; HRESULT hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &g_pd3dDevice, &featureLevel, nullptr); if (FAILED(hr)) { std::cout << "Failed to create DirectX 11 device." << std::endl; return false; }

// Obtenção da saída primária
IDXGIFactory1* pFactory = nullptr;
hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pFactory);
if (FAILED(hr))
{
    std::cout << "Failed to create DXGI factory." << std::endl;
    return false;
}

hr = pFactory->EnumAdapters1(0, &g_pOutput);
pFactory->Release();
if (FAILED(hr))
{
    std::cout << "Failed to get primary output." << std::endl;
    return false;
}

// Criação do objeto Desktop Duplication
IDXGIOutputDuplication* pDesktopDuplication = nullptr;
hr = g_pOutput->DuplicateOutput(g_pd3dDevice, &pDesktopDuplication);
if (FAILED(hr))
{
    std::cout << "Failed to create Desktop Duplication object." << std::endl;
    return false;
}

// QueryInterface para DXGIOutputDuplication 1.2
hr = pDesktopDuplication->QueryInterface(__uuidof(IDXGIOutputDuplication), (void**)&g_pDesktopDuplication);
pDesktopDuplication->Release();
if (FAILED(hr))
{
    std::cout << "Failed to get Desktop Duplication interface." << std::endl;
    return false;
}

return true;

}

// Função para capturar um quadro do jogo bool CaptureFrame(ID3D11Texture2D* pFrame) { DXGI_OUTDUPL_FRAME_INFO frameInfo; ID3D11Texture2D pAcquiredDesktopImage = nullptr;

// Captura do próximo quadro do jogo
HRESULT hr = g_pDesktopDuplication->AcquireNextFrame(500, &frameInfo, &pAcquiredDesktopImage);
if (hr == DXGI_ERROR_WAIT_TIMEOUT)
{
    // Não há alterações no quadro, continue com o quadro anterior
    return false;
}
else if (hr == DXGI_ERROR_ACCESS_LOST)
{
    // A captura foi perdida, reinicialize o dispositivo DirectX
    g_pDesktopDuplication->ReleaseFrame();
    g_pAcquiredDesktopImage->Release();
    g_pDesktopDuplication->Release();
    g_pOutput->Release();
    g_pd3dDevice->Release();
    InitializeDirectX();
    return false;
}
else if (FAILED(hr))
{
    std::cout << "Failed to acquire next frame." << std::endl;
    return false;
}

// Copia o quadro capturado para um novo objeto de textura
D3D11_TEXTURE2D_DESC desc;
pAcquiredDesktopImage->GetDesc(&desc);
hr = g_pd3dDevice->CreateTexture2D(&desc, nullptr, pFrame);
if (FAILED(hr))
{
    std::cout << "Failed to create texture for captured frame." << std::endl;
    return false;
}

ID3D11DeviceContext* pImmediateContext;
g_pd3dDevice->GetImmediateContext(&pImmediateContext);

pImmediateContext->CopyResource(*pFrame, pAcquiredDesktopImage);
g_pDesktopDuplication->ReleaseFrame();
pImmediateContext->Release();
pAcquiredDesktopImage->Release();

return true;

}

// Função para interpolar os quadros capturados void InterpolateFrames(ID3D11Texture2D pFrame1, ID3D11Texture2D pFrame2, ID3D11Texture2D** pInterpolatedFrame) { // Implemente a lógica de interpolação dos quadros capturados aqui // Você pode usar técnicas como interpolação bilinear ou bicúbica

// Exemplo de interpolação simples - média dos valores de pixel
ID3D11DeviceContext* pImmediateContext;
g_pd3dDevice->GetImmediateContext(&pImmediateContext);

pImmediateContext->CopyResource(*pInterpolatedFrame, pFrame1);
D3D11_MAPPED_SUBRESOURCE mappedResource1, mappedResource2, mappedResourceInterpolated;
pImmediateContext->Map(pFrame1, 0, D3D11_MAP_READ, 0, &mappedResource1);
pImmediateContext->Map(pFrame2, 0, D3D11_MAP_READ, 0, &mappedResource2);
pImmediateContext->Map(*pInterpolatedFrame, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResourceInterpolated);

// Itera sobre os pixels e realiza a interpolação
for (UINT y = 0; y < mappedResource1.RowPitch / 4; ++y)
{
    UINT* row1 = (UINT*)((BYTE*)mappedResource1.pData + y * mappedResource1.RowPitch);
    UINT* row2 = (UINT*)((BYTE*)mappedResource2.pData + y * mappedResource2.RowPitch);
    UINT* interpolatedRow = (UINT*)((BYTE*)mappedResourceInterpolated.pData + y * mappedResourceInterpolated.RowPitch);

    for (UINT x = 0; x < mappedResource1.RowPitch / 4; ++x)
    {
        UINT pixel1 = row1[x];
        UINT pixel2 = row2[x];

        // Interpolação simples - média dos valores de pixel
        UINT interpolatedPixel = (pixel1 + pixel2) / 2;

        interpolatedRow[x] = interpolatedPixel;
    }
}

pImmediateContext->Unmap(pFrame1, 0);
pImmediateContext->Unmap(pFrame2, 0);
pImmediateContext->Unmap(*pInterpolatedFrame, 0);
pImmediateContext->Release();

}

// Função para suavizar a exibição em tempo real void SmoothDisplay(ID3D11Texture2D* pInterpolatedFrame) { // Implemente a lógica de suavização da exibição em tempo real aqui // Você pode usar técnicas como filtro de média ou filtro gaussiano

// Exemplo de suavização simples - não faz nada
// Você pode substituir essa função pela implementação adequada

// Não faz nada

}

// Função principal int main() { if (!InitializeDirectX()) { std::cout << "Failed to initialize DirectX." << std::endl; return 1; }

ID3D11Texture2D* pFrame1 = nullptr;
ID3D11Texture2D* pFrame2 = nullptr;
ID3D11Texture2D* pInterpolatedFrame = nullptr;

while (true)
{
    if (CaptureFrame(&pFrame2))
    {
        if (pFrame1 != nullptr)
        {
            InterpolateFrames(pFrame1, pFrame2, &pInterpolatedFrame);
            SmoothDisplay(pInterpolatedFrame);
            // Exiba o quadro suavizado na tela

            pInterpolatedFrame->Release();
        }

        pFrame1 = pFrame2;
    }
}

// Libera recursos
pFrame1->Release();
g_pDesktopDuplication->Release();
g_pOutput->Release();
g_pd3dDevice->Release();

return 0;

}

Alternative behavior (optional) 近似的功能(可选)

No response

dtlnor commented 1 year ago

any description in english?

Blinue commented 1 year ago

Thanks for your code, but it doesn’t address the main issue.

  1. Interpolation needs to know at least two frames before and after, which implies that the screen has at least one frame of lag.
  2. The moment of interpolation is unpredictable, so it only works when the frame rate is far below the screen refresh rate.

Interpolation is only useful when integrated into the game, thinking that you can interpolate with third-party software is a naive idea.

marcos32123 commented 1 year ago

DLSS 3 utilizes frame interpolation, and FSR 3.0 will incorporate this feature. However, Magpie could potentially universalize this concept.

Blinue commented 1 year ago

Both integrating DLSS or FSR 2/3 are impossible. You should do some research first. I don’t want to repeat myself too many times😅

fatinghenji commented 1 year ago

Interpolation is only useful when integrated into the game, thinking that you can interpolate with third-party software is a naive idea.

在B站看到了利用reshade对星空添加dlss支持,请问是否能复刻进入magpie?还是说不是一个通用技术,需要针对某一游戏进行单独优化? 这是视频链接:https://www.bilibili.com/video/BV1km4y1T74P

【星空】DLSS3帧生成效果测试_哔哩哔哩bilibili
简介:展示一下在新亚特兰蒂斯开了DLSS3的效果,完全就是质变,从;更多实用攻略教学,爆笑沙雕集锦,你所不知道的游戏知识,热门游戏视频7*24小时持续更新,尽在哔哩哔哩bilibili 视频播放量 51009、弹幕量 57、点赞数 1193、投硬币枚数 368、收藏人数 481、转发人数 646, 视频作者 突破天际的金闪闪, 作者简介 FGO、明日方舟和Beat Saber UP主,现在已经成为偶尔才直播的咸鱼。https://afdian.net/a/PureDark,相关视频:星空开局就能获得的强力武器与服装,【表哥】评价星空,就是一坨屎!自由度也低,全是穿模,刚要代入黑屏读条了!无人深空才是真宇宙!,【寅子】试玩星空评价 女流 66:“我通关了”,不得不说星空的水效果是我见过游戏中最“吊”的!,【星空】DLSS帧数提升MOD+FOV视野修改教程,【星空MOD】N卡救星来了! DLSS2.0拯救渣优化 !提升游戏体验,星空逆天BUG,开局偷三体科技,3600块买星空典藏版,是什么体验?满满的正能量!,【星空】室友告诉我一分钟都不用剪(谁卡了?),帧数出乎预料!rog掌机《星空》全网首发测试体验!
Blinue commented 1 year ago

对游戏本身进行修改确实可以做到,但不能通用。