Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Мультимедия, OpenGL/DirectX > ID3DXFont::DrawText после сброса устройства


Автор: EgoBrain 21.5.2013, 08:39
Здравствуйте. Собственно требуется предпринять какие-то действия к объекту ID3DXFont после сброса устройства, так как метод DrawText вызывает исключение. Что нужно делать и почему я не знаю..
Код

...
ID3DXFont* g_font = NULL;
RECT font_rect;

...
D3DXCreateFont(iDevice, 22, 7, FW_NORMAL, 1, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "Arial", &g_font);
SetRect(&font_rect, 0, 0, 1024, 300);

...
Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
iDevice->BeginScene();

if(g_font) //--После сброса устройства, условие истино--
 g_font->DrawText(NULL,  "tro lo lo", -1, &font_rect, DT_LEFT|DT_NOCLIP,  0xFF000000); //--Студия указывает на эту строку--

iDevice->EndScene();
iDevice->Present(0, 0, 0, 0);


На всякий случай тект ошибки (хотя что он даст...):
Цитата

Unhandled exception at 0x0f8cb1fc in program.exe: 0xC0000005: Access violation writing location 0x0000f420.

Автор: Bitter 23.5.2013, 09:21
Уф давно уже не мучал директ, но если мне не изменяет память, то после сброса нужно пересоздать вообще все объекты, в том числе и iDevice, а следом за ним и g_font. Вы так и делаете?
Access violation всего лишь означает что вы обратились к объекту, который больше не существует или существует уже в другом месте. Так что нужно заново создать и проинициализировать все объекты после сброса.

Автор: EgoBrain 24.5.2013, 01:10
Дело в том что я плохо знаком с членами ID3DXFont, но вроде как многие интерфейсы Direct3D включают в себя автоматизированные средства (или просто стандартные обработчики событий) для штатных ситуаций типа сброса/потери устройства. Устройство пересоздавать не нужно после сброса (IDirect3DDevice9::Reset).
Пересоздание - решение в лоб, но не вижу в нём ничего плохого, нужно попробовать..

Добавлено через 6 минут и 34 секунды
Цитата(Bitter @  23.5.2013,  09:21 Найти цитируемый пост)
Access violation всего лишь означает что вы обратились к объекту, который больше не существует или существует уже в другом месте.

Как проверить доступность этого объекта?

Автор: EgoBrain 24.5.2013, 02:11
Немного доработал код, и вроде помогло, но почему то чайник перестал отображаться. Все равно непокидает чувство что что-то не так, не доведено до ума..
Код

...
D3DPRESENT_PARAMETERS d3dpp;
ID3DXFont* g_font = NULL;
RECT font_rect;
...
void Setup()
{
   D3DXCreateFont(iDevice, 22, 7, FW_NORMAL, 1, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "Arial", &g_font);
   SetRect(&font_rect, 0, 0, 1024, 300);
}
...
//--Сброс устройства при нажатии клавиши--
g_font->Release(); //--Удалить объект--
g_font = NULL;  //--Занулить указатель--
iDevice->Reset(&d3dpp);  //--Сбросить устройство--        

Setup();  //--Создать объект--
//---------------------------------------------------------
...
//--в цикле обрабтки сообщения окна -------------------------------------------------------------
Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
iDevice->BeginScene();
if(g_font) //--После сброса устройства, условие истино--
 g_font->DrawText(NULL,  "tro lo lo", -1, &font_rect, DT_LEFT|DT_NOCLIP,  0xFF000000);
iDevice->EndScene();
iDevice->Present(0, 0, 0, 0);
//--------------------------------------------------------------------------------------------------------------
...


Есть http://msdn.microsoft.com/en-us/library/windows/desktop/bb174714%28v=vs.85%29.aspx касательно потери устройства (Reset() инициирует потерю), есть http://www.gamedev.ru/code/forum/?id=81910.
Но все же не понятно что за методы OnLostDevice и OnResetDevice, когда их вызывать.. 

Автор: Bitter 24.5.2013, 12:33
Цитата(EgoBrain @  24.5.2013,  01:10 Найти цитируемый пост)
Как проверить доступность этого объекта?

К сожалению никак, разве что отлавливать исключение типа try...catch и по нему судить, но это костыль.

В 9м директе потеря устройства происходит, например, при переключении разрешения экрана. В этом случае пересоздавать устройство ОБЯЗАТЕЛЬНО. Кроме того при использовании Reset, точнее перед его использованием, вы ОБЯЗАНЫ удалить все буферы вершин, цепочки состояний, и тд и создать все это заново. Это обязательно, потому что при выполнении Reset, происходит утрата всех текстур, всех данных о вершинах в видеопамяти, а так же всех настроек рендера. 

Я не вижу этого у вас в коде, отсюда и ваши ошибки

Автор: kurlyak 11.6.2013, 00:42
От шо мне нравиться- все по- облому разобраться в проблеме. Лишь бы вставить свои 5 копеек.

Процедура рендеринга:

Код

void CMyApp::RenderScene()
{

    if( isDeviceLost() ) return;
.....


Код

bool CMyApp::isDeviceLost()
{
    
    HRESULT hr = p_d3d_Device->TestCooperativeLevel();

    if( hr == D3DERR_DEVICELOST )
    {
        Sleep(20);
        return true;
    }
    
    else if( hr == D3DERR_DRIVERINTERNALERROR )
    {
        MessageBox(0, "Internal Driver Error...Exiting", 0, 0);
        PostQuitMessage(0);
        return true;
    }
    
    else if( hr == D3DERR_DEVICENOTRESET )
    {
        onLostDevice();
        if(FAILED(p_d3d_Device->Reset(&d3dpp))) return false;
        onResetDevice();
        return false;
    }
    else
        return false;
}




Код

void CMyApp::onLostDevice()
{
    if(FAILED(pFont->OnLostDevice())) return;
}

void CMyApp::onResetDevice()
{
    if(FAILED(pFont->OnResetDevice())) return;

....


А при переключении- из Lost или Reset Device:

Код

void CMyApp::enableFullScreenMode(bool enable)
{
....
onLostDevice();
p_d3d_Device->Reset(&d3dpp);
onResetDevice();
....

Автор: EgoBrain 11.6.2013, 04:40
kurlyak, то есть пересоздавать ресурсы не нужно?

Цитата

if( hr == D3DERR_DEVICELOST )
    {
        Sleep(20);
        return true;
    }

Зачем тормозить поток? оО

onLostDevice и onResetDevice до и после ресета устройства вызывать только при переключении в фулскрин, а если я сглаживание или разрешение хочу поменять?
З.Ы. Просто из приведенного кода все равно не понятно как он поможет не терять ресурс pFont... Может я просто pFont->OnLostDevice()/OnResetDevice() не в том месте и не в то время вызывал...

Добавлено @ 04:45
А, и еще вопрос, хорошо ли постить сообщения окну для выхода в функции проверки устройства, может лучше ее результат получить из вызывающего блока и вдругом месте принимать решение...?

Добавлено позже
Кроме ID3DXFont у меня еще ID3DXMesh объект есть, он почему то после сброса не рисуется, даже после пересоздания (использовал тот же самый указатель).

Автор: EgoBrain 13.6.2013, 08:10
Mesh пересоздавать не требуется. Моя ошибка был в том, что я матрицу проекции не переустанавливал из-за чего не видно было сетку.
Устройство сброшено, значит сбросились все рендерстейты.
Но все равно некоторые вопросы и непонятки остаются. Хотелось бы полноценной статьи по вопросу сброса/потери smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)