Title: GPGPU Toolkit SlabOps
1GPGPU ToolkitSlabOps
- SlabOps were created by Mark Harris (UNC, NVIDIA)
2Main Issue with GPU Programming
- Main issue is not with writing the code for the
graphics card - The main issue is interfacing with the graphics
card
3Issues with Interfacing with GPUs
- You forget to do something
- Forget to initialize FBOs
- Forget to enable the CG program
- Forget to set the viewpoint correctly
- .
- GPGPU algorithms are hacks
- Youre rendering a quad to perform an algorithm
on an array - Its not object oriented
4Using SlabOps
- GPGPU methods covered previously are fine for
performing 1 or 2 programs - What about trying to manage ten or twenty
programs performing hundreds of passes? - SlabOps to the rescue!
5Using SlabOps
- SlabOps were created by Mark Harris while getting
his PHD at the University of North Carolina. - Used in his GPU Fluid Simulator to manage the
large number of fragment programs required for
each pass.
6Using SlabOps
- 3 Parts
- Define
- Define the type of SlabOp that you need (more on
this later) - Initialization
- Initialize the program to load
- Initialize the parameters to connect
- Initialize the output
- Run
- Update any parameters that might have changed
- Call Compute() to run the program
7Initialization
void initSlabOps() // Load the program
g_addMatrixfp.InitializeFP(cgContext,
"addMatrix.cg", "main") // Set the texture
parameters g_addMatrixfp.SetTextureParameter("te
x1", inputYTexID) g_addMatrixfp.SetTextureParam
eter("tex2", inputXTexID) // Set the texture
coordinates and output rectangle
g_addMatrixfp.SetTexCoordRect( 0,0, texSizeX,
texSizeY) g_addMatrixfp.SetSlabRect( 0,0,
texSizeX, texSizeY) // Set the output texture
g_addMatrixfp.SetOutputTexture(outputTexID,
texSizeX, texSizeY, textureParameters.texTarg
et, GL_COLOR_ATTACHMENT0_EXT)
8Run
g_addMatrixfp.Compute()
- One line to run the program
- Sets the variables
- Enables the program
- Sets the viewpoint
- Builds the geometry to perform the processing
- Perform the computation
- Get the output into the buffer or texture
- Disable the program
- Reset the viewpoint
9Comparing Saxpy (SlabOp)
SlabOp
// Do calculations for(int i 0 i numIterations i) g_saxpyfp.SetTexturePara
meter("textureY", yTexIDreadTex)
g_saxpyfp.SetOutputTexture(yTexIDwriteTex,
texSize, texSize, textureParameters.texTarg
et, attachmentpointswriteTex)
g_saxpyfp.Compute() swap()
10Comparing Saxpy (Non-SlabOp 1)
- // attach two textures to FBO
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
attachmentpointswriteTex, textureParameters.texT
arget, yTexIDwriteTex, 0) - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
attachmentpointsreadTex, textureParameters.texTa
rget, yTexIDreadTex, 0) - // check if that worked
- if (!checkFramebufferStatus())
- printf("glFramebufferTexture2DEXT()\t
FAIL\n") - // PAUSE()
- exit (ERROR_FBOTEXTURE)
- else if (mode 0)
- printf("glFramebufferTexture2DEXT()\t
PASS\n") -
- // enable fragment profile
- cgGLEnableProfile(fragmentProfile)
- // bind saxpy program
- cgGLBindProgram(fragmentProgram)
- // enable texture x (read-only, not changed
during the iteration) - cgGLSetTextureParameter(xParam, xTexID)
- cgGLEnableTextureParameter(xParam)
- // enable scalar alpha (same)
11Comparing Saxpy (Non-SlabOp 2)
- for (int i0 i
- // set render destination
- glDrawBuffer (attachmentpointswriteTex)
- // enable texture y_old (read-only)
- cgGLSetTextureParameter(yParam,
yTexIDreadTex) - cgGLEnableTextureParameter(yParam)
- // and render multitextured viewport-sized quad
- // depending on the texture target, switch
between - // normalised (0,12) and unnormalised
(0,wx0,h) - // texture coordinates
-
- // make quad filled to hit every pixel/texel
- // (should be default but we never know)
- glPolygonMode(GL_FRONT,GL_FILL)
- // and render the quad
- if (textureParameters.texTarget
GL_TEXTURE_2D) - // render with normalized texcoords
- glBegin(GL_QUADS)
12Comparing Saxpy
- Ok, that looked a little worse than we know it is
- But using SlabOps did look a little easier
- Saxpy only had one program being run for multiple
iterations. - What about something more complicated
- Fluid Flow
13Fluids
- Follow Stams method
- Were not going to cover how to do fluids so much
as the program flow and how SlabOps help contain
the problem
Fast Fluid Dynamics Simulation on the GPU, Mark
Harris. In GPU Gems.
- Advection
- Impulse
- Vorticity Confinement
- Viscous Diffusion
- Project Divergent Velocity
- Compute Divergence
- Compute Pressure Disturbances
- Subtract gradient(p) from u
- Display
14Lets not forget Boundary Conditions
Boundaries and interior are computed in separate
passes and may require separate programs
15Implementation
- Harris implementation contained 15 GPU programs
(including 4 for display) - The simulation takes about 20 passes for each
time-step, - (not including 2, 50 pass runs for the poisson
solver) - Switch to code
- (Note, code can be found in GPU Gems 1)
16Point
- Creating something as complex as a fluid solver
would be very difficult without some kind of
abstraction - So whats so special about SlabOps
- Versatility
- Policy-Based Design
17SlabOp Versatility
- Remember we skipped over how to define a SlabOp.
- Each SlabOp is actually composed of 6 objects
working together. - Each of the six objects can be replaced according
to the specific task - In other words to alter a SlabOp to display to
the screen instead of the back buffer, I just
replace the Update object.
18The 6 objects that define a SlabOp
- Render Target Policy
- Sets up / shuts down any special render target
functionality needed by the SlabOp - GL State Policy
- Sets and unsets the GL state needed for the
SlabOp - Vertex Pipe Policy
- Sets up / shuts down vertex programs
- Fragment Pipe Policy
- Sets up / shuts down fragment programs
- Compute Policy
- Performs the computation (usually via rendering)
- Update Policy
- Performs any copies or other update functions
after the computation has been performed
19Defining a SlabOp
- Luckily you do not need to create each of those
objects. - You just need to replace one when it doesnt do
what you want. - Harris created 3 predefined SlabOps
- DefaultSlabOp performs simple fragment program
rendered to a quad - BCSlabOp performs boundary condition fragment
program rendered as lines - DisplayOp displays a texture to the screen
20More complex SlabOps
- Objects defined to perform
- Flat 3d texture computations- computing for
voxel grids - Flat3DTexComputePolicy
- Flat3DBoundaryComputePolicy
- Flat3DVectorizedTexComputePolicy
- Copy3DTexGLUpdatePolicy
- Multi-texture output - rendering with multiple
texture outputs - MultiTextureGLComputePolicy
- Volume computations - rendering with multiple
texture coordinates - VolumeComputePolicy,
- VolumeGLComputePolicy
21Defining a SlabOp
typedef SlabOp NoopGLStatePolicy,
NoopVertexPipePolicy, GenericCgGLFragmentPipePolic
y, SingleTextureGLComputePolic
y, CopyTexGLUpdatePolicy DefaultSlabOp
Include a Noop where a policy is not used,
Include the preferred policy where one is needed
22Next Generation SlabOps?
- Version on course website has been extracted out
of Harris fluid simulator and updated to use
frame buffer objects instead of render texture - Easy to update SlabOps to use the geometry
processor also - Additional policies could be created to render to
non-quad surfaces, i.e. an object
23How do SlabOps work?
- The rest of this lecture will explain policy
based design. There will be no more GPU talk
during the remainder of the lecture - Why?
- SlabOps were a good implementation of Policy
Based Design - You should have some exposure to design patterns
and templates - Because Im the one holding the chalk.
24Where did Policy Based Design Come from?
- Modern C Design
- Generic Programming and Design Patterns Applied
- By Andrei Alexandrescu
- Excellent Bedtime reading
- - Asleep within 2 pages
- Contains unique implementations of
- design patterns using templates
25What is a design pattern?
- Design Pattern A general repeatable solution to
a commonly occurring problem in software
design. - Wikipedia (The irrefutable source on
everything) - The most commonly known design pattern?
26The Singleton
- One of the simplest and most useful design
pattern - Goal To only have one instance of an object, no
matter where it is created in the program
27The Singleton
- class Singleton
- public
- static Singleton Instance()
- Singleton()
- private
- static Singleton m_singleton
-
- Singleton SingletonInstance()
- if(m_singleton null)
- m_singleton new Singleton()
- return m_singleton
-
- // in Cpp file
- Singletonm_singleton null
28C Templates
- Templates functions that can operate with
generic types - The STL is a library of templates hence its name
Standard Template Library - Example Templates
- cout, cin
- vector
- string
Example Template
Example Template Use
template myType GetMax (myType a,
myType b) return (ab?ab)
int x,y GetMax (x,y)
Modern C Design Book on design patterns using
templates
29Policy Based Design
- Defines a class with a complex behavior out of
many little classes (called policies), each which
takes care of one behavioral or structural
aspect. - You can mix and match policies to achieve a
combinatorial set of behaviors by using a small
core of elementary components
30How it works
- Multiple Inheritance
- One class that inherits the properties of
numerous other classes - Templates
- Systems that operate with generic types
- Multiple Inheritance Templates Policy Based
Design
31Policies
- Each policy is a simple class that implements one
aspect of the overall goal - Policies do not need to be templates (in many
cases theyre not) - Policies do need to have specific known functions
that they implement
32Encapsulation Class
- One class needs to use multiple inheritance to
combine all the policies together
template GLStatePolicy, class VertexPipePolicy, class
FragmentPipePolicy, class ComputePolicy,
class UpdatePolicy class SlabOp public
RenderTargetPolicy, public
GLStatePolicy, public
VertexPipePolicy, public
FragmentPipePolicy, public
ComputePolicy, public
UpdatePolicy public SlabOp() SlabOp()
Compute()
33The Compute Method
- // The only method of the SlabOp host class is
Compute(), which - // uses the inherited policy methods to perform
the slab computation. - // Note that this also defines the interfaces
that the policy classes - // must have.
- void Compute()
-
- // Activate the output slab, if necessary
- ActivateRenderTarget()
- // Set the necessary state for the slab
operation - GLStatePolicySetState()
- VertexPipePolicySetState()
- FragmentPipePolicySetState()
-
- SetViewport()
- // Put the results of the operation into the
output slab. - UpdateOutputSlab()
34The Other Methods
- But wait, what about all the other functions that
we called inside our GPU program? - Those exist in the individual policies
- Example
- InitializeFP(CGcontext context, string
fpFileName, string entryPoint) - Exists in the FragmentPipePolicy
35Conclusion
- SlabOps are one of many GPGPU abstractions
- Happens to be my favorite because they are the
most versatile and are easy to use - Issues
- Does not include basic GPGPU functions such as
Reduce() - There is a learning curve
- Difficult to find out where things are actually
going on