Форум программистов, компьютерный форум, киберфорум
DirectX
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.91/11: Рейтинг темы: голосов - 11, средняя оценка - 4.91
31 / 31 / 15
Регистрация: 02.02.2015
Сообщений: 152

Вывод fps в чужой игре

02.11.2017, 11:34. Показов 2484. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем добрый день. Хочу сделать вывод fps в чужой игре. Внедряюсь в процесс игры, в данном случае приложение DirectX 11 - демка от Unity.
Запускаю демку, ставлю оконный режим 800x600. Далее подгружаю туда свою dll-ку. Всё отлично, счётчик кадров рисуется.
Если перейти в полноэкранный режим (Alt+Enter), то счётчик пропадает, то есть не рисуется на экране. Если перейти обратно,
то в оконном режиме он снова выводится нормально.
Если запустить демку сразу в полноэкранном режиме на разрешении равном разрешению экрана (у меня это 1440 на 900), то счётчик отображается нормально.

В чём может быть причина? У меня такое впечатление, что там две текстуры, в которые происходит рендеринг, и в зависимости от разрешения выводится одна из них?
Вот данные SwapChain после перехвата Present():

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
hr = swap->GetDesc(&swapChainDesc);
 
swapChainDesc.BufferDesc.Width = 800
swapChainDesc.BufferDesc.Height = 600
swapChainDesc.BufferDesc.RefreshRate.Numerator = 0 
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1 
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM (28)
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED (0)
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED (0)
 
swapChainDesc.SampleDesc.Count = 2
swapChainDesc.SampleDesc.Quality = 0 
 
swapChainDesc.BufferUsage = 48
swapChainDesc.BufferCount = 1
swapChainDesc.OutputWindow = 0x000000000006087c {unused=71304240 }
swapChainDesc.Windowed = 1
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD (0)
swapChainDesc.Flags = 2
Я так подозреваю, что на это влияет параметр: swapChainDesc.SampleDesc.Count = 2
И что тогда делать? Как выводить текст?
Это Multi-Sample Anti-Aliasing влияет на это или нет?

В окне (800x600):


В полноэкранном режиме (800x600):


В полноэкранном режиме (1440x900, разрешение экрана):
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
02.11.2017, 11:34
Ответы с готовыми решениями:

Альфа-смешивание в чужой игре
Здраствуйте уважаемые программисты. Появилась потребность смешать текстуру с другими в игре. Текстуру могу найти только примитивами (...

FPS в игре огромный
наедавно сделал небольшой апгрэйд купил материнку,проц,видяху.играл во многие игры Mass effect 60 fpf drakensng 320 fps Sims 3 аж...

Падает FPS в игре
Процессор: Intel Core i5-2310 2.9-GHz Мать: ASUS P8H61-V ОЗУ: 4096 DDR 1373MHz Блок Питания 450W Видеокарта: ATI Radeon HD 5750 ...

14
 Аватар для Byurrrer
6 / 6 / 0
Регистрация: 28.10.2017
Сообщений: 17
02.11.2017, 21:45
Цитата Сообщение от wmaster575 Посмотреть сообщение
Это Multi-Sample Anti-Aliasing влияет на это или нет?
MSAA не должен влиять, но могу ошибаться.

Отрисовка текста когда происходит (в какой момент)? Каким образом текст рисуется?

P.S. я в перехватах не спец))
0
31 / 31 / 15
Регистрация: 02.02.2015
Сообщений: 152
03.11.2017, 11:33  [ТС]
Byurrrer,
1. Перехватываю Present(), подменяю своей функцией.
2. Внутри своей функции сохраняю состояние контекста, далее рисую текст (треугольники и текстура алфавита, думаю, вы поняли о чём речь), восстанавливаю контекст.
3. Вызываю оригинальный Present().
0
 Аватар для Byurrrer
6 / 6 / 0
Регистрация: 28.10.2017
Сообщений: 17
03.11.2017, 11:45
wmaster575, понял, могут ли быть проблемы с позицией текста?
Цитата Сообщение от wmaster575 Посмотреть сообщение
У меня такое впечатление, что там две текстуры, в которые происходит рендеринг, и в зависимости от разрешения выводится одна из них?
При описанной выше схеме перехвата и рендера, внутренние установки самого движка не должны влиять, потому что рендер идет прямо в back buffer.
Еще:
BeginScene/EndScene должны использовать только единожды за проход рендера (если я не ошибаюсь), попробуй перехватывать EndScene. Они действительно влияют на рендер (хотя бы в dx9), у меня были некоторые проблемы в рендеер после вызова EndScene.

Добавлено через 2 минуты
Кстати, на своем приложении на dx11 (именно которое сам написал на чистом dx11 без использования движков) пробовал делать перехват?
0
31 / 31 / 15
Регистрация: 02.02.2015
Сообщений: 152
03.11.2017, 12:50  [ТС]
Byurrrer,
Нет, проблем с позицией текста быть не может, так как пробовал выводить в центр экрана текст, тоже самое.

При описанной выше схеме перехвата и рендера, внутренние установки самого движка не должны влиять, потому что рендер идет прямо в back buffer.
Да, согласен, но что тогда здесь?

BeginScene/EndScene должны использовать только единожды за проход рендера (если я не ошибаюсь), попробуй перехватывать EndScene. Они действительно влияют на рендер (хотя бы в dx9), у меня были некоторые проблемы в рендеер после вызова EndScene.
Пока пробую для DirectX 11, а там только одна функция Present(). Ещё ResizeBuffer(), её я тоже перехватываю.

Кстати, на своем приложении на dx11 (именно которое сам написал на чистом dx11 без использования движков) пробовал делать перехват?
Да, пробовал, всё работает. Но там swapChainDesc.SampleDesc.Count = 1, я думаю, что этот параметр как-то влияет.
0
 Аватар для Byurrrer
6 / 6 / 0
Регистрация: 28.10.2017
Сообщений: 17
03.11.2017, 12:58
Цитата Сообщение от wmaster575 Посмотреть сообщение
Пока пробую для DirectX 11, а там только одна функция Present().
Ничего толкового я не наюзал, к сожалению.
Цитата Сообщение от wmaster575 Посмотреть сообщение
Да, пробовал, всё работает. Но там swapChainDesc.SampleDesc.Count = 1, я думаю, что этот параметр как-то влияет.
Попробуй у себя в приложении тоже 2 поставить.
Больше нет у меня никаких мыслей.
0
31 / 31 / 15
Регистрация: 02.02.2015
Сообщений: 152
11.11.2017, 21:47  [ТС]
Byurrrer,
Я написал отдельную функцию MyPresentFunc4, в которой я только очищаю экран и всё, вызов ClearRenderTargetView().

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
HRESULT STDMETHODCALLTYPE MyPresent(IDXGISwapChain *swap, UINT SyncInterval, UINT Flags)
{
    HRESULT hr = S_OK;
    
    hr = MyPresentFunc4(swap, SyncInterval, Flags);
 
    hr = g_pOldPresent(swap, SyncInterval, Flags);
    return hr;
}
 
HRESULT STDMETHODCALLTYPE MyPresentFunc4(IDXGISwapChain *swap, UINT SyncInterval, UINT Flags)
{
    HRESULT hr = S_OK;
    bool bNext = true;
    ID3D11Device *pDevice = 0;
    ID3D11DeviceContext *pDeviceContext = 0;
    
    hr = swap->GetDevice(__uuidof(ID3D11Device), (void **)&pDevice);
    if (FAILED(hr))
    {
        bNext = false;
    }
    else
    {
        // Контекст.
        pDevice->GetImmediateContext(&pDeviceContext);
    }
 
    if (!bNext) return E_FAIL;
 
    ID3D11RenderTargetView *pRenderTargets[MAX_RENDER_TARGETS];
    pDeviceContext->OMGetRenderTargets(MAX_RENDER_TARGETS, pRenderTargets, NULL);
 
    float ClearColor[4] = { 0.0f, 0.0f, 1.0f, 1.0f };
 
    for (size_t i = 0; i < MAX_RENDER_TARGETS; i++)
    {
        if (pRenderTargets[i])
        {
            pDeviceContext->ClearRenderTargetView(pRenderTargets[i], ClearColor);
        }
    }
 
    for (size_t i = 0; i < MAX_RENDER_TARGETS; i++)
    {
        if (pRenderTargets[i]) pRenderTargets[i]->Release();
    }
 
    pDevice->Release();
    pDeviceContext->Release();
 
    return S_OK;
}
В оконном режиме экран очищается, но когда я перехожу в полноэкранный (ALT+ENTER), программа снова рисует как ни в чём не бывало.

Окно (640x480):


Полный экран (1440x900):


Видеозапись:


Что это за магия DirectX?
0
 Аватар для Byurrrer
6 / 6 / 0
Регистрация: 28.10.2017
Сообщений: 17
11.11.2017, 22:35
Цитата Сообщение от wmaster575 Посмотреть сообщение
MAX_RENDER_TARGETS
Что это?
wmaster575, уверен что MyPresent действительно в полноэкранном режиме вызывается? Как то узнать об этом можешь?
Цитата Сообщение от wmaster575 Посмотреть сообщение
if (pRenderTargets[i])
это условие точно выполняется в полноэкранном режиме?

Добавлено через 57 секунд
Цитата Сообщение от wmaster575 Посмотреть сообщение
Что это за магия DirectX?
похоже на какое-то "определенное" поведение.
0
31 / 31 / 15
Регистрация: 02.02.2015
Сообщений: 152
12.11.2017, 08:48  [ТС]
Byurrrer,

MAX_RENDER_TARGETS = 8, это максимальное кол-во RenderTargetView, которые можно установить для устройства D3D.
Я их всех перечисляю и вызываю ClearRenderTargetView() для очистки области.
Только 1 указатель имеет значение, все остальные равны NULL.

Цитата Сообщение от Byurrrer Посмотреть сообщение
Сообщение от wmaster575 if (pRenderTargets[i])
это условие точно выполняется в полноэкранном режиме?
Да.

На простом тестовом приложение DirectX всё выполняется, и в оконном и полноэкранном режиме.
0
 Аватар для Byurrrer
6 / 6 / 0
Регистрация: 28.10.2017
Сообщений: 17
12.11.2017, 16:31
Цитата Сообщение от wmaster575 Посмотреть сообщение
На простом тестовом приложение DirectX всё выполняется, и в оконном и полноэкранном режиме.
А на том что надо выполняется? Или нет? Нужен точный ответ.
0
31 / 31 / 15
Регистрация: 02.02.2015
Сообщений: 152
13.11.2017, 13:53  [ТС]
Да, выполняется. Но ещё раз сделаю проверку. Отпишу.

Добавлено через 20 часов 23 минуты
Цитата Сообщение от Byurrrer Посмотреть сообщение
А на том что надо выполняется? Или нет? Нужен точный ответ.
Да, MyPrsent вызывается и ClearRenderTargetView() в блоке тоже:
C++
1
2
3
4
if (pRenderTargets[i])
{
....
}
0
 Аватар для Byurrrer
6 / 6 / 0
Регистрация: 28.10.2017
Сообщений: 17
13.11.2017, 17:53
Тогда не могу ничего по этому поводу подсказать. Единственное что можно сделать это попытаться каким-то другим образом выводить fps, может быть через winapi?
Кстати, fraps нормально показывает свой fps в этом приложении?
0
31 / 31 / 15
Регистрация: 02.02.2015
Сообщений: 152
13.11.2017, 23:45  [ТС]
Byurrrer, fraps не пробовал, action выводит на ура, ocam выводит.
Я нашёл прогу RenderDoc для отладки DirectX приложений, можно посмотреть какие функции вызываются, и состояние конвейера. Завтра попробую разобраться.
0
31 / 31 / 15
Регистрация: 02.02.2015
Сообщений: 152
24.11.2017, 09:46  [ТС]
Byurrrer, разобрался.
В чём соль? Итак, что получается.
1. Когда движок Unity рисует в окно, то он рисует сразу в цепочку переключений, назовём SwapChain.
2. Когда движок рисует в полноэкранном режиме, то здесь два случая:
1) Если размеры окна равны размеру экрана (мы переключились в полноэкранный режим из окна), то будет использован SwapChain.
2) Если размеры окна (640x480) не равны размеру экрана (1440x900), то Unity будет рисовать вначале в промежуточную текстуру, назовём Texture1 (640x480), а затем пропорционально масштабировать её во SwapChain (1440x900).

Почему в Present() не получалось выводить изображение в полноэкранном режиме. Причина в следующем.
Алгоритм Unity такой (далее образно, главное суть):
1. Установить Texture1 в конвейер для рисования.
2. Настройка конвейера (шейдеры, ресурсы и т. д.).
3. Рисование сцены в Texture1.
4. Установить SwapChain в конвейер.
5. Настройка конвейера (шейдеры, ресурсы и т. д.).
6. Рисование сцены во SwapChain (то изображение, что будет на экране). На этом этапе масштаб. Texture1 во SwapChain.
7. Установить Texture1 в конвейер для рисования. (!!!)
8. Вызов Present(). Отображение буфера SwpChain на экране.

То есть, перед самым Present(), Unity ставит в конвейер обратно Texture1. поэтому когда я что-то рисую в перехваченном Present(), вывод идёт не на экран (SwapChain), а в промежуточную текстуру Texture1.
Выход следующий, надо установить SwapChain перед рисованием.

Вот примерный код функции, он рабочий. Часть функций вымышлена, приведена для примера. Комментарии в коде.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
HRESULT STDMETHODCALLTYPE HookPresent(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags)
{
    HRESULT hr;
 
    pSwapChain->GetDevice(__uuidof(pDevice), (void**)&pDevice);
    pDevice->GetImmediateContext(&pContext);
 
    // 1. Надо создать свой ViewPort и RenderTargetView.
 
    DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
    hr = pSwapChain->GetDesc(&swapChainDesc);
    if (SUCCEEDED(hr))
    {
        int nWidth = swapChainDesc.BufferDesc.Width;
        int nHeight = swapChainDesc.BufferDesc.Height;
 
        ZeroMemory(&vp, sizeof(vp));
        vp.Width = nWidth;
        vp.Height = nHeight;
        vp.MinDepth = 0.0f;
        vp.MaxDepth = 1.0f;
        vp.TopLeftX = 0;
        vp.TopLeftY = 0;
    }
 
    ID3D11Texture2D *pBackBuffer;
    hr = pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID *)&pBackBuffer);
    if (SUCCEEDED(hr))
    {
        pBackBuffer->Release();
        hr = pDevice->CreateRenderTargetView(pBackBuffer, NULL, &pTarget);
    }
 
    // 2. Сохраняем состояние конвейера.
    SaveState(pContext, &state);
 
    // 3. Устанавливаем наш ViewPort и RenderTargetView.
    pContext->OMSetRenderTargets(1, &pTarget, NULL);
    pContext->RSSetViewports(1, &vp);
 
    // 4. Рисуем, например текст.
    DrawOurText(L"Перехват Present()");
 
    // 5. Восстанавливаем состояние конвейера.
    RestoreState(pContext, &state);
    
    // 6. Уничтожим RenderTargetView.
    if (pTarget)
    {
        pTarget->Release();
        pTarget = NULL;
    }
 
    // 7. Вызов исходной Present().
    return OldHookPresent(pSwapChain, SyncInterval, Flags);
}
Такие дела.
0
 Аватар для Byurrrer
6 / 6 / 0
Регистрация: 28.10.2017
Сообщений: 17
04.12.2017, 23:20
wmaster575, поздравляю с найденным решением! Еще не добрался до изучения твоего решения, поставил в задачи)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
04.12.2017, 23:20
Помогаю со студенческими работами здесь

Скачки fps при игре
Здравствуйте, такая проблема: когда играю в какую либо игру - скачет фпс (при самом запуске 60-75, секунд через 5 падает до 20-30, потом...

Низкий FPS в игре Warface
Играю в Warface, но к сожалению с низким фпс, который скачет в основном от 20 до 30 , бывают просадки до 10-15, но не на долго. И это на...

Падение FPS в игре The Witcher 3
Доброго времени суток господа. Суть проблемы заключается в том, что когда захожу в игру, стабильно 60 фпс, после 10-20 минут, фпс...

Падение FPS в игре The witcher 2
Включаю ноутбук, захожу в стим далее в игру.. фпс в районе 60 Спустя 10-20 минут, фпс падает до 14. Что делать ? помогите пожалуйста ...

Падение FPS в игре The witcher 2
Создавал тему 9 месяцев назад https://www.cyberforum.ru/viruses/thread1954406.html в ней вы мне помогли разобраться с проблемой, но у...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru