Writing Direct3D Apps for Hardware Accelerators: The BeginScene()/EndScene() API Calls
The DirectX Team
August 2, 1996
Introduction
Proper use of Direct3D's BeginScene() and EndScene() is essential to making your application work properly with hardware 3-D accelerators. This article describes the operation of BeginScene() and EndScene() and gives guidelines for their use. Failure to follow these guidelines may cause your application to render incorrectly on a broad class of forthcoming 3-D hardware.
Definition
A scene in the Direct3D immediate mode is a collection of all the vertices and drawing primitives (triangles, lines, and points) used to draw a single frame. BeginScene() marks the beginning of a scene (and hence the start of a frame) and EndScene() marks the end of a scene (and hence the end of the frame).
In keeping with this definition, it is essential that all the execute buffer executions used to draw a single frame be bracketed by a single BeginScene()/EndScene() pair.
Justification
Correct use of BeginScene() and EndScene() is important to support a class of emerging 3-D hardware accelerators which do not use a conventional z-buffer to perform hidden surface removal. Such accelerators may implement a number of mechanisms for performing hidden surface removal (such as internal tiling and polygon sorting). However, to perform hidden surface removal, they all must process a copy of the entire geometric database for a single frame.
To accomplish this task, such accelerators must perform Scene Capture. In other words, they must store, for later processing, the geometric information passed to them via execute buffers.To ensure the hidden surface processing is correct, a single BeginScene() and EndScene() must bracket all the drawing instructions comprising a single frame. If multiple BeginScene() and EndScene() calls are made while composing a single frame, the accelerator will be unable to correctly resolve hidden surface interactions between triangles executed in different scene contexts.
Furthermore, an application should not assume that multiple BeginScene()/EndScene() calls per frame are permissible simply because it knows there are no hidden surface interactions between the triangles in different scene contexts. Certain accelerators use scene capture to perform high-quality rendering effects in addition to hidden surface removal. For example, a scene-capturing accelerator may be able to render shadows and semitransparent objects. These effects rely on the entire geometric database for a frame being available to the accelerator for processing. Multiple BeginScene() and EndScene() contexts will break such effects.
2-D and 3-D Interaction
Accelerators that perform scene capture probably will be unable to interleave 2-D drawing operations such as blits and direct writes with 3-D drawing operations in a scene context. Accelerators that have this restriction export the DirectDraw capability bit DDCAPS2_NO2DDURING3DSCENE. Therefore, an application should check this capability bit and, if it is present, not perform DirectDraw Blt(), GetDC(), or Lock() calls on the rendering surface between calls to BeginScene() and EndScene().
What to Do
To make sure that your application correctly renders on all 3-D accelerators (including those that perform scene capture), do the following:
1. Ensure that all the execution of execute buffers that hold triangles (and other rendering primitives instructions) for a single frame are preceded by a single call to BeginScene() and followed by a single call to EndScene().
2. Check the DirectDraw caps bit DDCAPS2_NO2DDURING3DSCENE. If it is set, do not call DirectDraw's Blt(), GetDC() or Lock() functions on the rendering surface between a call to BeginScene() and EndScene(). Such 2-D operations can be performed after EndScene() has been invoked.
3. Ensure that your application does not assume that any rendering primitives included in an execute buffer have been rendered to the target surface when Execute() returns. Scene capture cards will postpone rendering until the scene is complete (EndScene() has been called).