Ogre Reference Manual (ix) 5 hardware buffers

Source: Internet
Author: User

5 Hardware Buffers

Vertex, index, and pixel buffers inherit most of the Hardwarebuffer class characteristics. The basic premise of a hardware buffer is that the one by one blocks of memory that can be arbitrarily processed, no format (vertex, etc.), are completely dependent on the interpretation method used. In this respect, the hardware buffers are like the memory you allocate through malloc, except that it may be in the GPU or AGP storage.

5.1 Hardware buffer Management

The Hardwarebuffermanager class is the factory center in which all objects in the geometry system are created. The geometry of most objects you create and destroy is defined by this class. It is a singleton and can be accessed through Hardwarebuffermanager::getsingleton (), but it needs to be done after the rendering system is initialized (called root::initalise), because objects are created differently under different APIs. Although the public interface is used.

Cases:

vertexdeclaration* decl = Hardwarebuffermanager::getsingleton (). Createvertexdeclaration ();

Hardwarevertexbuffersharedptr vbuf = Hardwarebuffermanager::getsingleton (). CreateVertexBuffer (

3*sizeof (Real),//size of one whole vertex

Numvertices,//number of vertices

Hardwarebuffer::hbu_static_write_only,//usage

FALSE); No Shadow Buffer

5.2 Buffer Use

The memory of the hardware buffers is very competitive in rendering the scene, so the way in which the buffers are used is important, whether the contents of the buffers need to be updated frequently, and whether the data needs to be read from them are important factors that affect the graphics card management buffers. The best buffer type is that it does not require frequent updates and does not require reading. The methods and parameters for creating vertex and index buffers are different, but there is a common parameter usage:

hbu_static does not need to be updated frequently, but needs to be read

The hbu_static_write_only does not need to be updated frequently or read. However, if you can read from its shadow buffer, if set (see: Shadow Buffer). This is the best use option.

The hbu_dynamic needs to be updated frequently and needs to be read. This is the worst setting

hbu_dynamic_write_only are frequently updated, but do not require reading. However, if you can read from its shadow buffer, if set (see: Shadow Buffer). If you use this option, and you want to replace all the contents of each frame, you can use hbu_dynamic_write_only_discardable instead to achieve better performance on some platforms.

The hbu_dynamic_write_only_discardable needs to replace the entire contents of the buffer frequently, especially every frame. With this option, the system does not care about the loss of existing content, because you will soon be put in again after the loss. Some platforms can achieve significant performance. If you use this method, you need to use the HBL_DISCARD flag when locking to write content.

If you need to update the vertex buffers frequently, consider whether you really need to update all or part. In the latter case, consider using multiple buffers, marking only the data buffers that need to be modified as hbu_dynamic

Try _write_only form as much as possible. This means that you cannot read directly from the hardware buffer, which is a good practice because the read speed from the hardware buffer is slow. If you do need to read the data, you can use the shadow buffers described in the next section.

5.3 Shadow Buffers (shadow buffer)

Reading data from a hardware buffer is slow, and if you do need to read the data from the vertex buffer, you can set the Shadowbuffer parameter of CreateVertexBuffer or Createindexbuffer to true. This will create a copy of the hardware buffer in system memory, and you can get the same performance as reading normal memory. At the cost of writing, the system memory is updated first, and then the hardware buffers are updated with a separate copy process. As a result, additional overhead is generated when writing data. Do not use it unless you really need to use it.

5.4 Lock Buffer

If you are reading or updating a hardware buffer, you need to lock the buffer first. This will do two things: Tell the graphics card that you need to access the buffer (which affects the render queue) and get pointers to manipulating the data. Note: If you need to read the buffer, the contents of the hardware buffer will be copied to the system memory for access (you should not do so unless you set a shadow buffer for the buffer). It also needs to be unlocked after use, and if you lock the buffer for updates, the modified information will be updated to the graphics hardware.

Lock parameters

There are two methods of locking buffers:

Lock the entire buffer

Pbuffer->lock (LockType);

Locking section

Pbuffer->lock (start, length, lockType);

Locking a partial buffer is faster than locking all, because smaller batches of data are needed to lock out the hbl_discard tag.

Locking type LockType has a significant impact on performance, especially when a shadow buffer is not used, stating:

Hbl_normal is allowed to read and write, which is the worst performance. If you do not use a shadow buffer, this will cause the data to be transferred from the graphics card to the system memory and transferred back. If you use a shadow buffer, the impact is small.

hbl_read_only Read-only. The effect is best when using a shadow buffer (only the current read is good and the buffer is written slowly when it is created) because you do not need to download data from the graphics card.

hbl_discard Reference hbu_dynamic_write_only_discardable, which means you don't mind that the graphics card discards the contents of the entire buffer. This implies that you will not read the data from it, and that the graphics card avoids clogging when the buffer is being rendered (it can also be locked directly during rendering), because it actually gives you completely different data (that is, uninitialized memory, not overwriting with buffer content). Use this option whenever possible when the shadow buffer is not used. If you use a shadow buffer, this is very small, although it is best to use a shadow buffer to lock the entire buffer at once, allowing you to update the data to the buffer by using the Hbl_discard tag.

Hbl_no_overwrite is useful when the hbl_discard tag is locked only and therefore cannot be used. This tells the video card that you will not modify any part of the current frame rendering operation (unlocked part?). )。 Valid only if there is no shadow buffer.

After locking the buffer, you can do anything with the returned pointer (do not trouble yourself to read data locked with Hbl_discard or write hbl_read_only data). The modification of the content depends on the type of the buffer, the reference vertex buffer, the index buffer

5.5 Useful buffer Hints

1. Use buffers created with the hbl_static_write_only identity (without using shadow buffers) whenever possible, and generate data by Hbl_discard a single lock. Then don't visit it again

2. If you need to update the buffer frequently, use hbu_dynamic_write_only (same no shadow buffer) when creating, use Hbl_discard to lock the entire buffer, or use the Hbl_no_overwrite lock section if possible

3. If you do need to read the data from the buffer, create a shadow buffer. Locks are used only for reading using hbl_read_only to avoid uploading data when unlocking. You can mix the two points you said earlier and use static as much as possible. The _write_only can be safely used for reading.

4. It can be divided into multiple buffers when the vertices are used in different ways. Do not use a huge updatable buffer for vertex data, such as if you only need to update the texture coordinates, you can coordinate the texture into a separate buffer, the other uses hbu_static_write_only

Report:

The direct read performance from the hardware buffer is slow (optimized for writes), and if the need to read should use a shadow buffer, which actually puts two copies, the shadow buffers in the system memory are used for reading. Therefore, you should avoid reading as much as possible.

Memory access is also slow compared to CPU performance, so you should use Hbl_discard (no initial padding of memory) or use Hbl_no_overwrite (partial locking) to reduce memory access.

5.6 Hardware vertex buffers

This section specifically describes hardware vertex buffers, a general description of the hardware buffers, and corresponding creation, locking, reference hardware buffers

5.6.1 VertexData Class

The Vertexdata class brings together all the vertex-related information for geometry rendering.

The new Renderoperation class requires a vertexdata pointer, which is also used for mesh and Submesh to store vertex positions, normals, texture coordinates, and so on. Vertexdata can be used independently (rendering non-indexed geometry) or mixed with indexdata, where the triangular faces are defined by the index.

You do not need to use Vertexdata to store geometry data, you only need to provide vertexdata when rendering. This is easier because all members of vertexdata are pointers, so you can use an alternative structure to maintain your own vertex buffers, as long as you convert to Vertexdata at render time.

Important members of the Vertexdata:

Vertexstart vertex start range, can support multiple renderable share the same buffer

Vertexcount Vertex count

vertexdeclaration defines the Vertexdelaration object pointer in vertex format. Note: This object is created by Vertexdata for you, reference vertex declaration

vertexbufferbinding The Vertexbufferbinding object that defines the vertex buffer bindings, also created by Vertexdata for you, reference vertex buffer bindings

5.6.2 Vertex Declaration

Vertex declarations define the vertex input data for the rendered geometry. Vertex declarations allow you to define multiple data items (vertex elements, vertexelement classes) to support any number of buffers, multiple shares, or for a single element. You need to ensure that the content of the buffer is consistent with the purpose indicated by the vertex declaration

You can add elements using Vertexdelcaration::addelement, which include:

The buffer index used by the source element, the number of buffers used from 0 to the vertex data-1. Buffer pointers are used by index instead of directly to make it easier to rebind vertex data sources and avoid altering vertex format declarations.

    • offsets the offset element's number of bytes relative to the entire vertex data. If only one element is offset to 0, multiple elements are the sum of the dimensions of the preceding elements

Type element datatype (at the same time determines the size). This is important because the GPU is becoming more advanced and can no longer assume that the vertex position must be 3 floating-point numbers because the programmable vertex pipeline provides full control over the input and output. This section defines the type and size of the element, such as VET_FLOAT3, which represents 3 floating-point numbers, whose meaning is specified by the semantic parameter

The meaning of the semantic element is that the GPU uses this decision to input data, which indicates the semantics of the input data map when using a programmable pipeline. This identifies the element as position, normal, texture coordinate data, etc.

index is used when the same vertex declaration contains multiple identical semantics. For example, when more than one set of texture coordinates are used, the first group is 0 and the second group is 1.

You can add multiple semantics by calling addelement multiple times, while Vertexdelaration also provides a way to locate elements

Important Considerations

Theoretically you can completely control the format of vertices, but there are actually some limitations. The old DirectX hardware requires the following restrictions

1 vertex elements must be in the following order:

Position, blend weight, normal, diffuse color, mirror complexion, texture coordinates

2 buffers cannot have gaps that are not referenced by vertex elements

3 cannot make the Offest setting overlap two vertex elements

5.6.3 Vertex buffer Bindings

The vertex buffer binding is used to associate a vertex buffer to the source data index (source) of the vertex declaration

Create a vertex buffer

Hardwarevertexbuffersharedptr vbuf = Hardwarebuffermanager::getsingleton (). CreateVertexBuffer (

3*sizeof (Real),//size of one whole vertex

Numvertices,//number of vertices

Hardwarebuffer::hbu_static_write_only,//usage

FALSE); No Shadow Buffer

Vertex buffers are managed by hardwarevertexbuffersharedptr in a reference-count manner to be properly destroyed when used with multiple geometry sharing

Parameter description:

Vertexsize the byte size of a single vertex, a vertex can contain multiple elements.

Numvertices the number of vertices. You do not need to use all the vertices at once, you can create large buffers for multiple geometry sharing, because changing the vertex buffer bindings is a render state toggle and should Minimize

Usage Reference buffer use

Useshadowbuffer whether to use shadow buffers

Binding vertex buffers

Vertextdata->vertexbufferbinding->setbinding (0, VBUF);

Binding a buffer to an index 0

5.6.4 Updating vertex buffers

First lock, get pointers:

real* preal = static_cast<real*> (Vbuf->lock (Hardwarebuffer::hbl_discard)); Overwrite only

Note: Real should be float, otherwise there is a problem when compiling ogre with double precision

Based on the obtained pointer to write or read data directly, Ogre provides some auxiliary methods, for example:

Get Base pointer

unsigned char* Pvert = static_cast<unsigned char*> (vbuf->lock (hardwarebuffer::hbl_read_only));

real* Preal;

for (size_t v = 0; v < vertexcount; ++v)

{

Get elements

Vertexdeclaration::vertexelementlist Elems = Decl->findelementsbysource (BUFFERIDX);

Vertexdeclaration::vertexelementlist::iterator I, iend;

for (i = Elems.begin (); I! = Elems.end (); ++i)

{

vertexelement& elem = *i;

if (elem.getsemantic () = = ves_position)

{

Elem.basevertexpointertoelement (Pvert, &preal);

Write position using Preal

}

}

Pvert + = Vbuf->getvertexsize ();

}

Vbuf->unlock ();

Decl->findelementsbysource gets the list of elements associated with the buffer

Elem.basevertexpointertoelement (Pvert, &preal) calculates elem corresponding data offset pointer based on Pvert preal

Note: The example is that hbl_read_only is actually not writable (not updated to the hardware buffer) and should be Hbl_discard

5.7 Hardware Index Buffers

An index buffer constructs a triangle by referencing an indirect vertex, and as a vertex buffer can be used for multiple geometry sharing

5.7.1 Indexdata Class

Class summarizes the information used to draw geometry using an index, and the main members are:

Indexstart start index, useful when multiple geometries share the same index buffer

Indexcount Number of indexes

IndexBuffer buffer for placing index data

Creating an index buffer

Similar to vertex buffers

Hardwareindexbuffersharedptr ibuf = Hardwarebuffermanager::getsingleton (). Createindexbuffer (

Hardwareindexbuffer::it_16bit,//type of index

Numindexes,//number of indexes

Hardwarebuffer::hbu_static_write_only,//usage

FALSE); No Shadow Buffer

Parameter description:

Indextype index types are available in two types: 16bit and 32bit, and 32bit indexes are required when vertices are over 65526. The 32bit index is not supported on some old graphics cards. In addition, DIRECTX/OPENGL supports only 65,536 base primitives in a batch and can support up to 65536*3 indexes (up to 3 vertex indexes per entity) when using 32bit.

Numindexes Number of indexes

Usage buffer use

Useshadowbuffer whether to use shadow buffers

5.7.2 Updating index buffers

To get the data pointer first, the 16-bit index is unsigned short* and 32 bits is unsigned long*

unsigned short* pIdx = static_cast<unsigned short*> (ibuf->lock (Hardwarebuffer::hbl_discard))

The update is called after the unlock has committed data.

5.8 Hardware pixel Buffers

Hardware pixel buffers are graphics cards a special buffer for storing graphics data, commonly used in textures. A pixel buffer can represent 1-, two-, and three-dimensional images. A texture can be made up of over a buffer.

Pixel buffers cannot be constructed directly relative to vertex and index buffers. When a texture is created, the necessary pixel buffers are automatically constructed.

5.8.1 Texture

A texture refers to an image that can be applied to a three-dimensional model surface. Ogre, textures are represented by the texture class

Creating textures

Textures are created through the Texturemanger class, and most of the time are created directly by the Ogre resource system through image files. You can also create your own manually

Ptex = Texturemanager::getsingleton (). Createmanual (

"Mymanualtexture",//Name of texture

' General ',//Name of resource group in which the texture should be created

tex_type_2d,//Texture TYPE

,//Width

//Height

1,//Depth (must is 1 for both dimensional textures)

0,//number of mipmaps

PF_A8R8G8B8,//Pixel format

Tu_dynamic_write_only//Usage

);

Texture use

In addition to the use of hardware buffers, textures attach some uses:

Tu_automipmap is automatically generated by the graphics hardware mipmap, the specific algorithm is undefined, you can assume that the 2*2 box filter

Tu_rendertarget texture as a render target for rendering to textures, using this tag ignores tags except tu_automipmap

Tu_default equivalent to Ty_automipmap | Tu_static_write_only. The resource system uses this tag to load drawing files

Get pixel buffers

Textures may consist of multiple pixel buffers, each mipmap and polygon combination corresponding to a pixel buffer, which can be obtained by Texture::getbuffer (face, Mipmap):

For a cube texture, face represents the corresponding polygon, otherwise the faces are 0. Cases:

Get the Pixelbuffer for face 0, Mipmap 0.

Hardwarepixelbuffersharedptr ptr = Tex->getbuffer (0,0);

5.8.2 Updating pixel buffers

There are two ways to update a pixel buffer, all of which require the use of the Pixelbox object

Blitfrommemory

Manually loads an image and puts the contents in a manually created texture

Image img;

Img.load ("Elephant.png", "General");

Create RGB texture with 5 mipmaps

Textureptr tex = Texturemanager::getsingleton (). Createmanual (

"Elephant",

"General",

tex_type_2d,

Img.getwidth (), Img.getheight (),

5, PF_X8R8G8B8);

Copy face 0 mipmap 0 of the image to face 0 mipmap 0 of the texture.

Tex->getbuffer (0,0)->blitfrommemory (Img.getpixelbox (0,0));

This is the simplest way to blitfrommemory auto-complete format conversion and zooming

Direct Memory Lock

By locking, direct access to the contents of the buffer, for example:

Lock the buffer so we can write to it

Buffer->lock (Hardwarebuffer::hbl_discard);

Const Pixelbox &PB = Buffer->getcurrentlock ();

Image data starts at Pb.data and have format Pb.format

Here we assume Data.format are pf_x8r8g8b8 so we can address pixels as uint32.

UInt32 *data = static_cast<uint32*> (Pb.data);

size_t height = pb.getheight ();

size_t width = pb.getwidth ();

size_t pitch = Pb.rowpitch; Skip between rows of image

for (size_t y=0; y

{

for (size_t x=0; x<width; ++x)

{

0xRRGGBB, fill the buffer with yellow pixels

Data[pitch*y + x] = 0x00ffff00;

}

}

Unlock the buffer again (frees it for use by the GPU)

Buffer->unlock ();

5.8.3 Texture Type

tex_type_1d

tex_type_2d

TEX_TYPE_3D body texture, accessed through three-dimensional texture coordinates

Tex_type_cube_map cube map texture, consisting of 6 two-dimensional textures, accessed through three-dimensional texture coordinates

Cube map Texture

The six faces were

+x (face 0) (right).

-X (face 1) (left).

+y (face 2) (top).

-y (face 3) (bottom).

+z (face 4) (front! ).

-Z (face 5) (back! )

5.8.4 pixel format

The pixel format defines how encoding is encoded in pixel memory:

Native-ordered Integer (16, 24, 32bit) in memory of the local sequence format. An image formatted as PF_A8R8G8B8 can be viewed as a 32-bit array, defined as a hexadecimal 0xAARRGGBB.

BYTE Format (pf_byte_*)

Short Format (pf_short_*)

Float16 (pf_float16_*) only 5-bit exponent, 10-bit mantissa. No corresponding C++/CPU data type support, but faster support on the GPU

Float32 Format (pf_float32_*)

Compression format Pf_dxt[1-5] S3 Company's compressed texture format (S3TC)

Color Channel

RGB Red Green Blue

A Transparency Alpha

L Brightness Luminance

X Ignore

5.8.5 pixel box (pixel box)

Ogre all methods to process RAW image data through Pixcelbox, the main members include:

data Image memory pointer

format PixelFormat

rowpitch Number of rows, compressed texture same as getwidth

slicepitch Page (polygon) block number, compressed texture getwidth () *getheight ()

Left, top, right, bottom, front, back

Common methods

GetWidth () Width

GetHeight () high

Getdepth () high and deep

Getrowskip () line void Rowpictch–getwidth ()

Getsliceskip () page void Slicepitch-(getheight () * rowpitch)

Isconsecutive () whether continuous

Setconsecutive () is set to continuous (does not process actual data)

Ogre Reference Manual (ix) 5 hardware buffers

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.