Причина, по которой вы не нашли ссылок на GraphicsDevice.Begin/EndScene()
, заключается в том, что эти методы не существуют.Класс GraphicsDevice
- это управляемый класс, используемый для инкапсуляции графических функций, требуемых пользователем платформы XNA;это не однозначное отображение родного интерфейса IDirect3DDevice9
.
Я полагаю, глядя на исходный код, который вы имеете в виду, используя что-то вроде Reflector, и я также предполагаю, что вы смотрите накод как код C #.Важно помнить, что большие части структуры XNA написаны на C ++ / CLI, и, следовательно, при отражении в C # результаты могут быть несколько непредсказуемыми.
Для конкретного случая вызовов кродные IDirect3DDevice9::BeginScene()
и IDirect3DDevice9::EndScene()
, вам нужно немного покопаться.
Все последующее предполагает XNA 4.0.3.1 все равно должен быть похожим .В Reflector вы заметите, что класс GraphicsDevice
имеет приватный bool
_insideScene
.Если вы проанализируете это, вы увидите, что оно установлено в разных местах, например, вызов GraphicsDevice.DrawPrimitives()
.Отражение этого метода в C # должно установить этот член со следующим кодом:
if (!this._insideScene)
{
**(((int*) this.pComPtr))[0xa4](this.pComPtr);
this._insideScene = true;
}
Ключевая строка здесь - **(((int*) this.pComPtr))[0xa4](this.pComPtr);
.Если бы вы написали сборку C ++ / CLI, включили соответствующие заголовки DirectX (d3d9.h
) и вызвали BeginScene()
в экземпляре IDirect3DDevice9
(то есть pDevice->BeginScene()
), а затем разобрали вашу сборку в C #, вы бы получилилиния, идентичная вышеупомянутой.Вот как IL для нативного вызова отображается обратно в C #, , но невозможно написать эту строку в C # и скомпилировать ее .
Строка кода по сути является необработанной виртуальнойвызов метода.Вы можете прочитать более подробную информацию о таблицах виртуальных методов здесь , но для этой ситуации необходимо следующее: указатель виртуальной таблицы объекта (зависимый от компилятора, но истинный в этой ситуации) первый элементв родном объекте.pComPtr
- это небезопасный указатель на собственный объект COM IDirect3DDevice9
.Следовательно, разыменование pComPtr
(*pComPtr
) дает указатель на таблицу виртуальных методов.Разборка здесь немного неоднозначна, но ИЛ довольно ясен.Далее происходит добавление 0xa4
к указателю таблицы виртуальных методов.Чтобы понять это, помните, что собственные массивы - это просто указатель на первый элемент массива.Таблица виртуальных методов объекта - это массив указателей на функции.0xa4
- 164 в десятичном виде, что означает, что указатель перемещается на 164 байта вперед.Поскольку библиотека является библиотекой x86, указатели имеют длину 4 байта.Это означает, что мы перешли к 41-му методу в таблице виртуальных методов (164 / 4 = 41
).Если вы посмотрите на объявление интерфейса IDirect3DDevice9
в d3d9.h
(часть DirectX SDK), вы увидите, что 41-й метод - BeginScene
.Этот указатель затем разыменовывается, чтобы получить фактический метод BeginScene
, а затем вызывается, передавая (обычно скрытый) указатель this
в качестве первого (и единственного) параметра (где this
для собственного вызова - this.pComPtr
указатель).
Подобный код можно увидеть в закрытом небезопасном методе GraphicsDevice.Present()
, на этот раз со смещением 0xa8
или в функции 42, равной IDirect3DDevice9::EndScene()
.
Поэтому выможно увидеть, что GraphicsDevice
правильно гарантирует, что BeginScene
был вызван до того, как будет выполнено любое рисование, и EndScene
вызывается до того, как вызывается собственный метод IDirect3DDevice9::Present()
, но он намеренно скрывает эту функциональность от пользователей платформы XNA.