Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The reason you didn't find references to <code>GraphicsDevice.Begin/EndScene()</code> is because those methods don't exist. The <code>GraphicsDevice</code> class is a managed class used to encapsulate the graphics functionality required by a user of the XNA framework; it is not a one to one mapping of the native <code>IDirect3DDevice9</code> interface.</p> <p>I assume by looking at the source code you mean using something like Reflector, and I'm also assuming that you're looking at the code as C# code. One thing that is important to keep in mind is that large portions of the XNA framework are written in C++/CLI and consequently when reflected to C# the results can be somewhat unpredictable.</p> <p>For the specific case of calls to the native <code>IDirect3DDevice9::BeginScene()</code> and <code>IDirect3DDevice9::EndScene()</code>, you need to dig a little.</p> <p><strong>All the following assumes XNA 4.0. 3.1 should still be similar</strong>. In Reflector, you'll notice the <code>GraphicsDevice</code> class has a private <code>bool</code> <code>_insideScene</code>. If you analyse this, you'll see it set in various locations, such as the <code>GraphicsDevice.DrawPrimitives()</code> call. The C# reflection of this method should set this member with the following code:</p> <pre><code>if (!this._insideScene) { **(((int*) this.pComPtr))[0xa4](this.pComPtr); this._insideScene = true; } </code></pre> <p>The key line here is <code>**(((int*) this.pComPtr))[0xa4](this.pComPtr);</code>. If you were to write a C++/CLI assembly, include the appropriate DirectX headers (<code>d3d9.h</code>) and call <code>BeginScene()</code> on an instance of <code>IDirect3DDevice9</code> (i.e. <code>pDevice-&gt;BeginScene()</code>) and then disassemble your assembly in C#, you would have a line identical to the above. This is how the IL for the native call maps back to C#, <strong>but it is not possible to write that line in C# and compile it</strong>.</p> <p>The line of code is essentially a raw virtual method call. You can read more information about virtual method tables <a href="http://en.wikipedia.org/wiki/Virtual_method_table" rel="noreferrer">here</a>, but the bare-bones of it for this situation is as follows: an object's virtual table pointer is (compiler dependent, but true in this situation) the first element in a native object. <code>pComPtr</code> is an unsafe pointer to the native COM <code>IDirect3DDevice9</code> object. Therefore, dereferencing <code>pComPtr</code> (<code>*pComPtr</code>) gives you the pointer to the virtual method table. The dissassembly is a bit ambiguous here, but the IL is fairly clear. What happens next is <code>0xa4</code> is added to the virtual method table pointer. To understand this, remember that native arrays are just a pointer to the first element of the array. An object's virtual method table is an array of function pointers. <code>0xa4</code> is 164 in decimal, meaning the pointer is moved forward 164 bytes. As the library is an x86 library, pointers are 4 bytes long. This means that we have moved to the 41st method in the virtual method table (<code>164 / 4 = 41</code>). If you have a look at the <code>IDirect3DDevice9</code> interface declaration in <code>d3d9.h</code> (part of the DirectX SDK), you'll see that the 41st method is <code>BeginScene</code>. This pointer is then dereferenced to give the actual <code>BeginScene</code> method, and then called passing in the (normally hidden) <code>this</code> pointer as the first (and only) parameter (where <code>this</code> for the native call is the <code>this.pComPtr</code> pointer).</p> <p>You can see similar code in the private unsafe <code>GraphicsDevice.Present()</code> method, this time offsetting to <code>0xa8</code>, or function 42, which is <code>IDirect3DDevice9::EndScene()</code>.</p> <p>Therefore, you can see the <code>GraphicsDevice</code> correctly ensures that <code>BeginScene</code> has been called before any drawing is done, and <code>EndScene</code> is called before the native <code>IDirect3DDevice9::Present()</code> method is called, but it deliberately hides this functionality from users of the XNA framework.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload