Опубликован: 28.04.2009 | Доступ: свободный | Студентов: 1840 / 107 | Оценка: 4.36 / 4.40 | Длительность: 16:40:00
Специальности: Программист
Лекция 1:

Введение в XNA Framework

Лекция 1: 123456789 || Лекция 2 >
Direct3D9: :====> ENTER: DLLMAIN(042dd6e0): Process Attach: 00000298,
 tid=00000910
Direct3D9: :====> EXIT: DLLMAIN(042dd6e0): Process Attach: 00000298
Direct3D9: (INFO) :Direct3D9 Debug Runtime selected.
D3D9 Helper: Enhanced D3DDebugging disabled; Application was not
 compiled with D3D_DEBUG_INFO
Direct3D9: (INFO) :======================= Hal SWVP device selected
Direct3D9: (INFO) :HalDevice Driver Style 9 Direct3D9: 
:DoneExclusiveMode
// Предупреждение. К устройству, не рассчитанному на работу в
 многопоточном режиме (в
// конструкторе класса GraphicsDevice указан флаг 
CreateOptions.SingleThreaded)
// пытается обратиться другой поток.
Direct3D9: (WARN) :Device that was created without 
D3DCREATE_MULTITHREADED is being used by a thread 
other than the creation thread.
// Ошибка! Устройство может быть уничтожено только потоком, 
создавшим его
Direct3D9: (ERROR) :Final Release for a device can only 
be called from the thread that the device was created from.
Direct3D9: (WARN) :Device that was created without 
D3DCREATE_MULTITHREADED is being used by a thread 
other than the creation thread.
Direct3D9: (WARN) :Device that was created without 
D3DCREATE_MULTITHREADED is being used by a thread 
other than the creation thread.
Direct3D9: (WARN) :Device that was created without 
D3DCREATE_MULTITHREADED is being used by a thread 
other than the creation thread.
Direct3D9: (WARN) :Device that was created without D
3DCREATE_MULTITHREADED is being used by a thread other 
than the creation thread.
Direct3D9: :====> ENTER: DLLMAIN(042dd6e0): Process 
Detach 00000298, tid=00000520
Direct3D9: (INFO) :MemFini!
Direct3D9: :====> EXIT: DLLMAIN(042dd6e0): Process
 Detach 00000298

Хотя приложение и работает нормально, по отладочным сообщениям можно легко догадаться, что при завершении работы приложения сборщик мусора попытался уничтожить устройство, что естественно не удалось – ведь сборщик мусора вызывает методы Finalize в отдельном потоке, в то время как устройство Direct3D может удалить лишь тот поток, который его создал. Таким образом, отладочная версия DirectX помогла нам легко локализовать проблему.

Единственное неудобство доставляют отличия между Direct3D и XNA Framework. К примеру, устройство Direct3D по умолчанию запускается в однопоточном режиме, а включение поддержки многопоточного режима осуществляется путем указания флага D3DCREATE_MULTITHREADED. А вот класс GraphicsDevice, напротив, по умолчанию создаeт графическое устройство с поддержкой многопоточности, а отключение данной функциональности осуществляется путем указания флага CreateOptions.SingleThreaded. Кроме того, отладочная версия Direct3D нечего не знает о .NET Framework – вместо того, чтобы сообщить о проблемах из-за удаления объекта GraphicsDevice сборщиком мусора она просто жалуется на странное поведение непонятно откуда взявшегося дополнительного потока. Впрочем, получив некоторый опыт чтения сообщений отладочной версии Direct3D, вы перестанете обращать внимание на подобные нюансы.

Взаимодействие XNA Framework c DirectX

Как говорилось выше, XNA Framework по сути является прослойкой между .NET и DirectX. Но насколько эта тонка прослойка и оказывает ли она существенное влияние на производительность приложения? Чтобы ответить на этот вопрос мы рассмотрим работу XNA Framework на примере метода

Direct3D.Device.Present, декомпилировав его с использованием .NET Reflector, который находится в example.zip в каталоге Tools\NET Reflector:

public unsafe void Present()
{
// Проверяет, не был ли вызван метод Dispose для данного 
экземпляра класса
// GraphicsDevice. Если метод Dispose уже был вызван, 
генерируется исключение
// ObjectDisposedException
InternalHelper.CheckDisposed(this, (void*) this.pComPtr); 
// Получает указатель на COM–интерфейс IDirect3DDevice9, 
являющийся низкоуровневым 
// аналогом класса GraphicsDevice.
IDirect3DDevice9* devicePtr1 = this.pComPtr; 
// Вызывает COM-метод IDirect3DDevice9::Present, 
который выполняет переключение 
// буферов и вывод изображения на экран. К сожалению, 
.NET Reflector сгенерировал, 
// мягко говоря, не самый красивый код.
int num1 = **(((int*) devicePtr1))[0x44](devicePtr1, 0, 0, 0, 0);
// Если метод IDirect3DDevice9::Present возвратил 
отрицательное значение, то есть во 
// время выполнения метода произошла ошибка 
(в COM отрицательные значения 
// соответствуют кодам ошибок). if (num1 < 0) 
{ 
// Если код ошибки равен -2005530520 (соответствует потере устройства)
 if (num1 == -2005530520) 
{ 
// Подготовка к вызову обработчика события DeviceLost 
(если он определен) с 
// последующим вызовом. Тема потери устройства будет 
рассмотрена в разделе 1.2.4. EventArgs args1 = EventArgs.Empty;
EventHandler handler1 = this.<backing_store>DeviceLost;
if (handler1 != null)
{
handler1(this, args1); 
}
} 
// Генерируется исключение. Класс исключения и текст сообщения 
об ошибке определяется 
// кодом, который вернул Com-метод IDirect3DDevice9::Present
throw ExceptionHelper.GetExceptionFromResult(num1); 
} 
}

Как видно, метод GraphicsDevice.Present содержит вызов COM -метода IDirect3DDevice9::Present плюс небольшую обвязку для взаимодействия с COM. Иными словами, на платформе Windows метод GraphicsDevice.Present по сути является обвязкой над методом . Впрочем, на других платформах всe может быть совершенно иначе.

1.2.2. Конфигурирование проектов в Visual Studio 2005

В этом разделе мы рассмотрим тонкости настройки свойств проекта в среде Visual Studio 2005 с учeтом специфики приложений, использующих XNA Framework. Если вы имеете большой опыт работы с Visual Studio, можете пропустить этот раздел.

Как вы знаете, самой крупной единицей Visual Studio 2005 является решение ( Solution ), описание которого хранятся в текстовом файле формата XML с расширением .sln. Каждое решение состоит из одного или нескольких проектов: набора файлов исходного кода и ресурсов, которые будут откомпилированы в одну сборку (исполняемый файл .exe или динамическую библиотеку .dll ).Файлы с описанием проектов, использующих язык C#, имеют расширение .csproj. Файлы исходного кода C# -программы имеют расширение .cs, файлов ресурсов - .resx и т.д. В принципе для получения представления о структуре решения достаточно открыть любой проект и взглянуть на вкладку Solution Explorer (рисунок 1.4).

Примечание

Возможность хранить несколько проектов внутри одного решения очень полезна при разработке сложных приложений. К примеру, вы можете держать в одном решении 4 проекта: библиотека моделирования искусственного интеллекта, редактор уровней, собственно игра и еe инсталлятор. Эта возможность будет довольно активно использоваться в ряде примеров курса.

Проект может иметь несколько конфигураций, позволяющих быстро переключаться между различными настройками проекта. При создании нового проекта Visual Studio 2005 добавляет в него две конфигурации:

Debug и Release.

  • Конфигурация Debug предназначена для отладки приложения. При использовании этой конфигурации приложение компилируется без использования оптимизаций, а в .exe файл добавляются отладочные символы. Благодаря этому отладчик может найти однозначное соответствие между полученным двоичным кодом и исходным текстом программы, что позволяет осуществлять пошаговое выполнение программы, просмотр промежуточных значений переменных и т.п. Кроме того, программист, используя директивы условной компиляции, может добавлять в отладочную версию кода ряд разнообразных дополнительных расширенных проверок вводимых данных.
  • Конфигурация Release применяется для построения финальной версии приложения. В этом случае компилятор применяет различные оптимизации: удаление лишних переменных, перестановка инструкций, разворачивание циклов и т.п. Это значительно повышает производительность приложения (иногда в десятки раз), однако значительно усложняет отладку, которая возможна лишь на уровне машинного кода.
  • Переключение между этими конфигурациями легко осуществляется с использованием выпадающего списка на панели инструментов Visual Studio (рисунок 1.10). Вообще, конфигурации Debug и Release отличаются между собой лишь настройками различных свойств. Теоретически, проигравшись со свойствами конфигурации Debug, вы можете легко превратить еe в функциональный аналог конфигурации Release и наоборот. Кроме того, вы можете добавить в решение некоторые специфические конфигурации вроде "Release Shareware Version", "Release Full Version" и т.д.
 Переключение между различными конфигурациями с использованием панели инструментов

Рис. 1.10. Переключение между различными конфигурациями с использованием панели инструментов

Примечание

Так как конфигурации Debug и Release генерируют очень сильно различающийся код, иногда возникают ситуации, когда ошибка в программе проявляется только Debug или Release -коде. Поэтому я настоятельно рекомендую вам тестировать промежуточные версии вашей программы в обоих режимах.

Лекция 1: 123456789 || Лекция 2 >
Андрей Леонов
Андрей Леонов

Reference = add reference, в висуал студия 2010 не могу найти в вкладке Solution Explorer, Microsoft.Xna.Framework. Его нету.