200 likes | 332 Views
Cg & the GPU. Old-school, General Purpose Use of the GPU for Everything, But …. What is the GPU Pipeline?. Then, What is a Shader?. What is Cg ?. Originally, Customizable Shaders were Written in Assembly or a Specialized Vector Languages.
E N D
Cg& the GPU Old-school, General Purpose Use of the GPU for Everything, But …
What is Cg? • Originally, Customizable Shaders were Written in Assembly or a Specialized Vector Languages. • C for Graphics is a high-level GPU shader language designed, developed and implemented by NVIDIA. • Simple C Syntax compiles out to assembly, GLSL or HLSL code, in various formats, for many versions of DirectX and OpenGL.
Cg Language Features? • Constructors, e.g. float4 v = float4(a,b,c,d); • Array Operator, e.g. v[0], v[1], v[2], or v[3] • Swizzle Operator Can Reorder Data: • e.g. v.xyz, v.xxxz, v.yyx, v.yx, v.xyzw • Replaceable with rgba instead of xyzw • Vectorized Primitives: float2, float3, float4 • 16-bit Floating Point Constructs: half, half2, … • Fixed Precision Decimals: fixed, fixed2, …
Cg Language Features? • Matrices are Compounded Vector Classes, e.g. float4x4, and are Constructed with multiple vectors • float4 v = float4(a,b,c,d); • float4x4 m = float4x4(v,v,v,v); • Samplers Texture Data Type • sampler1D, sampler2D, samplerRECT, sampler3D • samplerRECT: Same as sampler2D but uses pixel locations as texture coordinates instead of [0,1]
Basic Cg Vertex Shader struct C2E1v_Output { float4 position : POSITION; float4 color : COLOR; }; C2E1v_Output C2E1v_green(float2 position : POSITION) { C2E1v_Output OUT; OUT.position = float4(position, 0, 1); OUT.color = float4(0, 1, 0, 1); // RGBA green return OUT; }
Basic Cg Fragment Shader struct C2E2f_Output { float4 color : COLOR; }; C2E2f_Output C2E2f_passthrough(float4 color : COLOR) { C2E2f_Output OUT; OUT.color = color; return OUT; }
Cg: O(n) vs O(n3) CPU GPU
Cg: O(n) vs O(n3) CPU GPU
Create Texture from Data voidshScene::GPU_CreateTextureDataForModel( shObject * oi ) { // determine the texture dimensions modelTexColumnCount = numDataFromModel*floatArraySize; //formalize the texture's modelHeight and modelWidth modelWidth = numDataFromModel;//number of data pieces to store wide modelHeight = oi->NList.size; //number of nodes to store high modelTexSize = modelWidth*modelHeight*floatArraySize; textureData = newfloat[modelTexSize]; //Copy all the data from the cloth to the texture inti = 0; float * position = newfloat [floatArraySize]; float * velocity = newfloat [floatArraySize]; for( node * currentNode = oi->NList.head; currentNode != NULL; currentNode = currentNode->next ) { currentNode->getPosition(position); //Model Data: 0-pos, 1-force, 2-vel for( int j = 0; j < floatArraySize; j++ ) { textureData[i+j] = position[j]; textureData[i+j+floatArraySize] = 0.0f;//force textureData[i+j+2*floatArraySize] = 0.0f; } i+=modelTexColumnCount; } free(position); }
Execute GPU from C++ voidshScene::GPU_ExecuteGPGPU( CGprogramfragmentProgram, GLuintspringData, intspringIndex ) { //Prepare Frame Buffer Object (FBO) glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, GPUFrameBuffer ); if( texSwap ) { // Bind output texture glDrawBuffer( GL_COLOR_ATTACHMENT1_EXT ); } else { // Bind output texture glDrawBuffer( GL_COLOR_ATTACHMENT0_EXT ); } // get ready to run this specific fragment program cgGLBindProgram(fragmentProgram); cgGLEnableProfile(cgFragmentProfile); // Create and enable the TEXTURE parameter for the fragment program cgTexture0 = cgGetNamedParameter(fragmentProgram, "modelData"); if( texSwap ){ cgGLSetTextureParameter(cgTexture0, m_imageLoader->m_itexNum[GPU_Data_Texture_0]); } else { cgGLSetTextureParameter(cgTexture0, m_imageLoader->m_itexNum[GPU_Data_Texture_1]); } cgGLEnableTextureParameter(cgTexture0); [continued below …] }
Execute GPU from C++ voidshScene::GPU_ExecuteGPGPU( CGprogramfragmentProgram, GLuintspringData, intspringIndex ) { [continued from above …] //enable additional custom options if( fragmentProgram == cgCalculateSpringForcesOnGPU ) { // Create and enable the STANDARD parameters for the fragment program cgTextureSpringIndex = cgGetNamedParameter(fragmentProgram, "springIndex"); cgGLSetParameter1f(cgTextureSpringIndex, springIndex); // Create and enable the TEXTURE parameter for the fragment program cgTexture1 = cgGetNamedParameter(fragmentProgram, "springData"); cgGLSetTextureParameter(cgTexture1, m_imageLoader->m_itexNum[springData]); cgGLEnableTextureParameter(cgTexture1); } elseif( fragmentProgram == cgUpdateVelocityOnGPU ) { // Create and enable the STANDARD parameters for the fragment program cgEnforceFixedNode = cgGetNamedParameter(fragmentProgram, "enforceFixed"); • //static for now, make this dynamic later • cgGLSetParameter1f(cgEnforceFixedNode, 1.0f); } • // Render the Texture to the Buffer on a Simple Quad • GPU_WriteQuadAndTextureToBuffer(modelWidth, modelHeight); • // Disable the Texture Parameter for this specific Fragment Program • cgGLDisableTextureParameter(cgTexture0); if( fragmentProgram == cgCalculateSpringForcesOnGPU ) cgGLDisableTextureParameter(cgTexture1); cgGLDisableProfile(cgFragmentProfile); texSwap = !texSwap; }
Executing on the GPU //Fragment Program used to add gravity force to Y force vector Fragment_OutputCalculateGravityForcesOnGPU( float2 textCoord : TEXCOORD0, uniform samplerRECTmodelData ) { //simply pass the data through if not force fragment Fragment_Output OUT; OUT.color = texRECT( modelData, textCoord ); //Model Data: 0-position, 1-force, 2-velocity if( CorrectFragment( textCoord.x, FORCE_5f ) ) { //we are at the force position, index set by adding 2 OUT.color += MASS*gravityVector;//F=MA } return OUT; }
Get Data Back From GPU voidshScene::GPU_RestoreDataFromTexture( shObject * oi ) { • glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );//Restore render buffer float * texture = newfloat[modelTexSize]; if( RESET_MODEL ) {// Reset texture data on the graphics card with original text glBindTexture( GL_TEXTURE_RECTANGLE_NV, m_imageLoader->m_itexNum[GPU_Data_Texture_RESET] ); RESET_MODEL = false;//our damage is done here } else { glBindTexture( GL_TEXTURE_RECTANGLE_NV, m_imageLoader->m_itexNum[GPU_Data_Texture_1] ); } glGetTexImage( GL_TEXTURE_RECTANGLE_NV, 0, GL_RGB, GL_FLOAT, texture ); • resize(m_iwidth, m_iheight); // Change to PROJ float * position = newfloat [floatArraySize]; for( node * currentNode = oi->NList.head; currentNode != NULL; currentNode = currentNode->next ) { for( int j = 0; j < floatArraySize; j++ ) { position[j] = texture[i+j]; } currentNode->setPosition(position); i+=modelTexColumnCount; } glDisable(GL_FRAGMENT_PROGRAM_NV); //Disable our Custom GPU Rendering glDisable(GL_TEXTURE_RECTANGLE_NV); }