Click here to Skip to main content
15,881,715 members
Articles / Multimedia / DirectX

DirectX10 Geometry Shader with Stream Output

Rate me:
Please Sign up or sign in to vote.
2.47/5 (6 votes)
10 Oct 2012CPOL4 min read 52.2K   1K   10   14
GS-SO tutorial for basic effects

Introduction

This article introduces DirectX10 (and DX11) with Geometry shader to novice and intermediate level graphics programmers. The attached code is to be referred while going through this article.

Stream output is also demonstrated here to read back values from the GPU.

Background

Geometry shader is the latest addition to the DX10 APIs, it gives programmers an ability to spawn new and destroy existing geometry using the graphics hardware, and this allows fancier effects such as explosions, realistic growth, decay, (add new effects here :-) ) etc. without reloading the mesh.

Using the Code

The attached solution is created using VS2010-Beta2 and uses library files from DirectX-SDK (Aug/2009).

The first block explains creation of DirectX device, the objective here is to instantiate the device object to access methods to perform operations on the GPU.

DirectX device like any COM device must be created by using class factory. Fortunately, DX-SDK allows the programmer to do this via global APIs, this allows DX programming with minimum COM exposure except for the fact that every COM object is required to be released to avoid memory leaks.

C++
D3D10CreateDeviceAndSwapChain( NULL, D3D10_DRIVER_TYPE_HARDWARE , 
	NULL,0, D3D10_SDK_VERSION, &sd, &pSwapChain, &pd3dDevice );

D3D10CreateDeviceAndSwapChain creates the device and the swap chain. Through the swap chain we get the back buffer (back buffering is used for flicker free animation). We then use the device to create a render target and use the back buffer to write on (please refer to the code).

The next block shows us how to create a vertex layout.

We first specify the layout for the vertices, this can done by using structure (refer to code). The vertex layout is required to tell the DX driver about the vertex format it can expect from the user. In the following example, we have specified that the first 3 floats are x-y-z coordinates and the next 2 will be texel coordinates.

C++
D3D10_INPUT_ELEMENT_DESC

D3D10_INPUT_ELEMENT_DESC layout[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 }, 
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 }, 
};
UINT numElements = sizeof(layout)/sizeof(layout[0]);
D3D10_PASS_DESC PassDesc;
pTechnique->GetPassByIndex( 0 )->GetDesc( &PassDesc );
ID3D10InputLayout *pVertexLayout=0;
pd3dDevice->CreateInputLayout(layout, numElements, PassDesc.pIAInputSignature, 
	PassDesc.IAInputSignatureSize, &pVertexLayout );

We then have to set the vertex buffer layout using:

C++
pd3dDevice->IASetInputLayout( pVertexLayout );

This vertex layout will be set as active layout, you can always set active layout multiple times during rendering depending on the vertex layout required for different objects, (most DX10 based engines expect only one type of layout):

C++
struct SimpleVertex
{
D3DXVECTOR3 Pos; // Position
D3DXVECTOR2 Tex; // Texture Coordinate
};
SimpleVertex vertices[] = { D3DXVECTOR3( 0.5f, 0.5f, 0.0f ),
	D3DXVECTOR2(1.0,1.0), D3DXVECTOR3( -0.5f, -0.5f, 0.0f ),
	D3DXVECTOR2(0.0,0.0), D3DXVECTOR3( -0.5f, 0.5f, 0.0f ),D3DXVECTOR2(0.0,1.0), };

Notice that only three vertices are provided. This is important so as to provide coordinates of a triangle.

We then create a memory buffer for GPU read access and set it to use the coordinates specified in the simple vertex structure (refer to the code). This will help us to pump the vertex data to the GPU, note that this data must be aligned as per the active vertex layout discussed earlier:

C++
...
InitData.pSysMem = vertices;
...
pd3dDevice->CreateBuffer( &bd, &InitData, &pVertexBuffer );

We then load the FX file (the shader file:- effects.txt) which holds the program for vertex shader, geometry shader, pixel shader, the object created is an effects pointer, this pointer can be used for setting up rendering similar to DX9-D3D.

Note that unlike DX9, the vertex shader here is required as fixed point transformations have been removed and all transformations have to be done by using the vertex shader and by passing parameters to variables set up in the vertex shader.

The Pixel shader is required to control rendering (and texturing as seen in the attached sample code), we can alter rendering by setting up variables for different effects (I might write an article about this later).

The geometry shader is not really required, we need it here … well it’s the reason why I am writing this article. Please refer to code to view how the effects pointer has been used to get the ID3D10EffectTechnique pointer which is used within the render loop.

C++
D3DX10CreateEffectFromFile( L"effects.txt", NULL, NULL, "fx_4_0", 
D3D10_SHADER_ENABLE_STRICTNESS, 0, pd3dDevice, NULL,NULL, &pEffect, &pErrors, NULL );

Notice the geometry shader in the effects.txt file.

The Geometry shader is created using:

C++
GeometryShader gStream=ConstructGSWithSO( CompileShader( gs_4_0, GS() ),"SV_POSITION.xyz" ); 
	SetGeometryShader( gStream); //to set the geometry shader

In the attached solution, the geometry shader is used to spawn an additional triangle using command: TriStream.Append. After executing this shader in the effects pass, the output on screen will result in a square (two triangles). Now comes the part to read back values from the graphics card.

This is done in three parts:

  1. The first involves creating a temporary buffer with CPU access, and the other to dump vertex data into.
    C++
    sbdesc.CPUAccessFlags =D3D10_CPU_ACCESS_READ ; //notice this setting 
    		//pd3dDevice->CreateBuffer( &sbdesc, NULL, &pStaging );
  2. The next step is to set streaming output (SO) using SOSetTargets(1,&pBuff,&offset). Note that in the effects file (effects.txt), the GS shader has been created using SO.
  3. The last step is to copy the data from the dump to the temporary buffer for reading purposes (or feedback: used to simulate growth effects). This is done by calling pd3dDevice->CopyResource(pStaging,pBuff);
    C++
    D3DXVECTOR3 *ptr = 0; 	//since buffer is created with 
    			//D3D10_BIND_VERTEX_BUFFER pStaging->Unmap();

Points of Interest

The Geometry shader with stream output can also be modified to provide GPGPU since we are now able to read back values from the GPU with ease.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Instructor / Trainer
India India
Hi,
I have been working with computers since my eight grade, programming the ZX Spectrum. I have always had an interest in assembly language and computer theory (and is still the reason for taking tons of online courses), actively code using C/C++ on Windows (using VS) and Linux (using QT).

I also provide training on data structures, algorithms, parallel patterns library , Graphics (DX11), GPGPUs (DX11-CS,AMP) and programming for performance on x86.
Feel free to call me at 0091-9823018914 (UTC +5:30)



(All views expressed here do not reflect the views of my employer).

Comments and Discussions

 
QuestionAdded OpenGL GS based tessellation Pin
Asif Bahrainwala13-Aug-15 5:19
Asif Bahrainwala13-Aug-15 5:19 
GeneralMy vote of 5 Pin
uj_13-Dec-10 19:22
uj_13-Dec-10 19:22 
GeneralDX11 sample for GS-SO [modified] Pin
Asif Bahrainwala20-Feb-10 6:40
Asif Bahrainwala20-Feb-10 6:40 
GeneralMy vote of 1 Pin
Jim Crafton26-Jan-10 5:03
Jim Crafton26-Jan-10 5:03 
GeneralRe: My vote of 1 Pin
Asif Bahrainwala31-Jan-10 9:53
Asif Bahrainwala31-Jan-10 9:53 
GeneralRe: My vote of 1 Pin
Asif Bahrainwala31-Jan-10 22:22
Asif Bahrainwala31-Jan-10 22:22 
GeneralPoor Article Pin
Justin Helsley22-Jan-10 13:07
Justin Helsley22-Jan-10 13:07 
GeneralRe: Poor Article Pin
Asif Bahrainwala31-Jan-10 9:51
Asif Bahrainwala31-Jan-10 9:51 
GeneralMy vote of 2 Pin
Justin Helsley22-Jan-10 13:04
Justin Helsley22-Jan-10 13:04 
Poor Article. Weak Explanations. Articles are about writing... this is little more than a link to a code file.
General[My vote of 1] Need more information and formatting Pin
Richard MacCutchan22-Jan-10 2:14
mveRichard MacCutchan22-Jan-10 2:14 
GeneralCorrupted zip file Pin
Alexandre GRANVAUD21-Jan-10 23:32
Alexandre GRANVAUD21-Jan-10 23:32 
GeneralRe: Corrupted zip file Pin
Asif Bahrainwala31-Jan-10 9:49
Asif Bahrainwala31-Jan-10 9:49 
GeneralKnew it was you :) Pin
sumitkm21-Jan-10 19:00
sumitkm21-Jan-10 19:00 
GeneralRe: Knew it was you :) Pin
Asif Bahrainwala31-Jan-10 9:48
Asif Bahrainwala31-Jan-10 9:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.