[SOLVED] CS WIN32

$25

File Name: CS_WIN32.zip
File Size: 75.36 KB

5/5 - (1 vote)

OpenCL / OpenGL Vertex Buffer Interoperability: A Particle System Case Study
Also, see the video at:

Copyright By Assignmentchef assignmentchef

This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License
Computer Graphics
mjb March 27, 2021
opencl.opengl.vbo.pptx

OpenCL / OpenGL Vertex Interoperability: The Basic Idea
Your C++ program writes initial values into the buffer on the GPU
(x,y,z) Vertex Data in an OpenGL Buffer
OpenCL acquires the buffer
Each OpenCL kernel reads an (x,y,z) value from the buffer
Each OpenCL kernel updates its (x,y,z) value
Each OpenCL kernel writes its (x,y,z) value back to the buffer
OpenCL releases the buffer
OpenGL draws using the (x,y,z) values in the buffer on the GPU
Computer Graphics
mjb March 27, 2021

Some of the Inner Workings of OpenGL:
Feel Free to Detour Right to Slide #24 if You Dont Want to Know This
Computer Graphics
mjb March 27, 2021

In the Beginning of OpenGL
You listed the vertices with separate function calls:
glBegin( GL_TRIANGLES ); glVertex3f( x0, y0, glVertex3f( x1, y1, glVertex3f( x2, y2,
z0 ); z1 ); z2 );
z0 ); z3 ); z4 );
glVertex3f( x0, y0, glVertex3f( x3, y3, glVertex3f( x4, y4,
Then someone noticed how inefficient that was, for three reasons:
1. Sending large amounts of small pieces of information is less efficient than sending small amounts of large pieces of information
2. The vertex coordinates were being listed in the CPU and were being transferred to the GPU every drawing pass
3. Some vertices were listed twice
Computer Graphics
mjb March 27, 2021

Heres What OpenGL Has Been Moving To: Vertex Buffer Objects
GLfloat CubeVertices[ ][3] = {
{ -1., -1., -1. }, { 1., -1., -1. }, { -1., 1., -1. }, { 1., 1., -1. }, { -1., -1., 1. }, { 1.,-1., 1.}, {-1., 1., 1.}, { 1., 1., 1.}
GLfloat CubeColors[ ][3] = {
GLuint CubeIndices[ ][4] = {
{ 0, 2, 3, 1 }, { 4, 5, 7, 6 }, { 1, 3, 7, 5 }, { 0, 4, 6, 2 }, { 2, 6, 7, 3 }, { 0, 1, 5, 4 }
Computer Graphics
mjb March 27, 2021
{ 0., 0., 0. }, { 1., 0., 0. }, { 0., 1., 0. }, { 1., 1., 0. }, { 0., 0., 1. }, { 1., 0., 1. }, { 0., 1., 1. }, { 1., 1., 1. },

A Little Background the OpenGL Rendering Context
The OpenGL Rendering Context contains all the characteristic information necessary to produce an image from geometry. This includes transformations, colors, lighting, textures, where to send the display, etc.
Array Buffer
Element Array Buffer
Texture0 Texture1 Context Dest. Transformation
If we were implementing the OpenGL state as a C++ structure (which were not), we might do something like this:
struct context {
float [4][4]
struct Texture *
struct DataArrayBuffer *
} Context;
Color; Transformation; Texture0; ArrayBuffer;
Computer Graphics
mjb March 27, 2021

More Background
How do you create a special OpenGL Array Buffer called a Vertex Buffer Object?
In C++, objects are pointed to by their address.
In OpenGL, objects are pointed to by an unsigned integer handle. You can assign a value for this handle yourself (not recommended), or have OpenGL generate one for you that is guaranteed to be unique. For example:
GLuint buf; glGenBuffers( 1, &buf );
This doesnt actually allocate memory for the buffer object yet, it just acquires a unique handle. To allocate memory, you need to bind this handle to the Context.
Computer Graphics
mjb March 27, 2021

More Background What is an OpenGL Object?
An OpenGL Object is pretty much the same as a C++ object: it encapsulates a group of data items and allows you to treat them as a unified whole. For example, a Data Array Buffer Object could be defined in C++ by:
struct DataArrayBuffer {
enum void * int
dataType; memStart; memSize;
Then, you could create any number of Buffer Object instances, each with its own characteristics encapsulated within it. When you want to make that combination current, you just need to point the ArrayBuffer element of the Context to that entire struct (bind). When you bind an object, all of its information comes with it.
Computer Graphics
mjb March 27, 2021

A Little Background the OpenGL Rendering Context Its very fast to re-bind a different vertex buffer. It
amounts to just changing a pointer.
glBindBuffer( GL_ARRAY_BUFFER, buf );
Array Buffer
Element Array Buffer
Texture0 Texture1 Context Dest. Transformation
Computer Graphics
mjb March 27, 2021

More Background Binding to the Context
The OpenGL term binding refers to attaching or docking (a metaphor which I find to be more visually pleasing) an OpenGL object to the Context. You can then assign characteristics, and they will flow through the Context into the object.
Vertex Buffer Object
Array Buffer
Element Texture0 Texture1 Array BufferContext
Lighting Transformation
glBindBuffer( GL_ARRAY_BUFFER, buf );
glBufferData( GL_ARRAY_BUFFER, numBytes, data, usage );
Think of it as happening this way:
Context.ArrayBuffer.memStart = CopyToGpuMemory( data, numBytes ); Context.ArrayBuffer.memSize = numBytes;
Computer Graphics
mjb March 27, 2021

More Background Binding to the Context
When you want to use that Vertex Buffer Object, just bind it again. All of the characteristics will then be active, just as if you had specified them again.
Vertex Buffer Object
Transformation
Array Buffer
Element Texture0 Texture1 Array BufferContext
Lighting Transformation
glBindBuffer( GL_ARRAY_BUFFER, buf );
Computer Graphics
mjb March 27, 2021
Think of it as happening this way:
float *data = Context.ArrayBuffer.memStart;

Vertex Buffers: Putting Data in the Buffer Object
glBufferData( type, numBytes, data, usage );
type is the type of buffer object this is:
GL_ARRAY_BUFFER to store floating point vertices, normals, colors, and texture coordinates
numBytes is the number of bytes to store in all. Not the number of numbers, but the number of bytes!
data is the memory address of (i.e., pointer to) the data to be transferred to the graphics card. This can be NULL, and the data can be transferred later via memory-mapping.
Computer Graphics
mjb March 27, 2021

Preview: We are going to use a Particle System as a Case Study
Computer Graphics
mjb March 27, 2021

Vertex Buffers: Putting Data in the Buffer Object
glBufferData( type, numbytes, data, usage );
usage is a hint as to how the data will be used: GL_xxx_yyy
where xxx can be:
STREAM this buffer will be written lots
STATIC this buffer will be written seldom and read often DYNAMIC this buffer will be written often and used often
and yyy can be:
DRAW this buffer will be used for drawing READ this buffer will be copied into
COPY not a real need for now, but someday
Computer Graphics
GL_STATIC_DRAW is the most common usage
mjb March 27, 2021

Vertex Buffers: Step #1 Fill the Arrays
GLfloat Vertices[ ][3] = {
{ 1., 2., 3. }, { 4., 5., 6. },
int numVertices = sizeof(Vertices) / ( 3*sizeof(GLfloat) );
Computer Graphics
mjb March 27, 2021

Vertex Buffers: Step #2 Create the Buffers and Fill Them
glGenBuffers( 1, &buf );
glBindBuffer( GL_ARRAY_BUFFER, buf );
glBufferData( GL_ARRAY_BUFFER, 3*sizeof(GLfloat)*numVertices, Vertices, GL_STATIC_DRAW );
Computer Graphics
mjb March 27, 2021

Vertex Buffers: Step #3 Activate the Array Types That You
glEnableClientState( type )
where type can be any of:
GL_VERTEX_ARRAY GL_COLOR_ARRAY GL_NORMAL_ARRAY GL_TEXTURE_COORD_ARRAY
Call this as many times as you need to enable all the arrays that you will need. There are other types, too.
To deactivate a type, call:
glDisableClientState( type )
Computer Graphics
mjb March 27, 2021

Vertex Buffers: Step #4 To Draw, First Bind the Buffers
glBindBuffer( GL_ARRAY_BUFFER, buf );
Vertex Buffer Object
Transformation
Array Buffer
Element Texture0 Texture1 Array BufferContext
Lighting Transformation
Computer Graphics
mjb March 27, 2021

Vertex Buffers: Step #5 Specify the Data
Vertex Data
Color Data
glVertexPointer( size, type, stride, rel_address); glColorPointer( size, type, stride, rel_address); glNormalPointer( type, stride, rel_address); glTexCoordPointer( size, type, stride, rel_address);
size is the spatial dimension, and can be: 2, 3, or 4 type can be:
Vertex Data
Color Data
Vertex Data
Color Data
Vertex Data
Color Data
GL_SHORT GL_INT
stride is the byte offset between consecutive entries in the array (0 means tightly packed)
Computer Graphics
rel_address, the 4th argument, is the relative byte address from the start of the buffer where the first element of this part of the data lives.
mjb March 27, 2021

The Data Types in a vertex buffer object can be stored either as packed or interleaved
gl*Pointer( size, type, stride, offset);
rel_address, the 4th argument, is the relative byte address from the start of the buffer where the first element of this part of the data lives.
Vertex Data
Color Data
glVertexPointer( 3, GL_FLOAT, 3*sizeof(GLfloat), 0 );
glColorPointer( 3, GL_FLOAT, 3*sizeof(GLfloat), 3*numVertices*sizeof(GLfloat));
stride start
Vertex Data
Color Data
Vertex Data
Color Data
Vertex Data
Color Data
Interleaved:
Computer Graphics
mjb March 27, 2021
glVertexPointer( 3, GL_FLOAT, 6*sizeof(GLfloat), 0 ); glColorPointer( 3, GL_FLOAT, 6*sizeof(GLfloat), 3*sizeof(GLfloat) );

Vertex Buffers: Step #6 Specify the Connections
GLfloat Vertices[ ][3] = {
{ x0, y0, z0 }, { x1, y1, z1 }, { x2, y2, z2 }, { x3, y3, z3 }, { x4, y4, z4 }, { x5, y5, z5 }
int numVertices = sizeof(Vertices) / ( 3*sizeof(GLfloat) );
glDrawArrays( GL_TRIANGLES, 0, numVertices );
Computer Graphics
mjb March 27, 2021

Vertex Buffers: Writing Data Directly into a Vertex Buffer
Map the buffer from GPU memory into the memory space of the application:
glBindBuffer( buf, GL_ARRAY_BUFFER );
glBufferData( GL_ARRAY_BUFFER, 3*sizeof(float)*numVertices, NULL, GL_STATIC_DRAW );
float * vertexArray = glMapBuffer( GL_ARRAY_BUFFER, usage );
usage is an indication how the data will be used:
Allocates the bytes, but doesnt deliver any data
GL_READ_ONLY GL_WRITE_ONLY GL_READ_WRITE
the vertex data will be read from, but not written to the vertex data will be written to, but not read from the vertex data will be read from and written to
You can now use vertexArray[ ] like any other floating-point array.
When you are done, be sure to call:
Computer Graphics
mjb March 27, 2021
glUnMapBuffer( GL_ARRAY_BUFFER );

We Now Pickup with the OpenCL Stuff
Computer Graphics
mjb March 27, 2021

We Now Pickup with the OpenCL Stuff
Computer Graphics
mjb March 27, 2021

Either OpenGL or OpenCL can use the Vertex Buffer at a time, but not both: All of this happens on the GPU
Your C++ program writes initial values into the buffer on the GPU
(x,y,z) Vertex Data in an OpenGL Buffer
OpenCL acquires the buffer
Each OpenCL kernel reads an (x,y,z) value from the buffer
Each OpenCL kernel updates its (x,y,z) value
Each OpenCL kernel writes its (x,y,z) value back to the buffer
OpenCL releases the buffer
OpenGL draws using the (x,y,z) values in the buffer on the GPU
Computer Graphics
mjb March 27, 2021

1. Program Header
#include
#define _USE_MATH_DEFINES #include
#include
#include
#include
#include
#ifdef WIN32
#include #endif
#ifdef WIN32 #include glew.h #endif
#include #include #include glut.h #include glui.h
#include CL/cl.h #include CL/cl_gl.h
Computer Graphics
mjb March 27, 2021

Structures We to Fill the Vertex Buffers
// structs we will need later:
struct xyzw {
float x, y, z, w;
struct rgba {
float r, g, b, a;
Computer Graphics
mjb March 27, 2021

OpenCL Global Variables
size_t GlobalWorkSize[3] = { NUM_PARTICLES, 1, 1 };
GLuint GLuint struct xyzw * cl_mem cl_mem cl_mem
cl_command_queue cl_device_id cl_kernel cl_platform_id cl_program
LocalWorkSize[3] = { LOCAL_SIZE, 1, 1 };
hPobj; hCobj; hVel; dPobj; dCobj; dVel;
// host opengl object for Points
// host opengl object for Colors
// host C++ array for Velocities
// device memory buffer for Points
// device memory buffer for Colors
// device memory buffer for Velocities
CmdQueue; Device; Kernel; Platform; Program;
Computer Graphics
mjb March 27, 2021

A Deceptively-Simple Main Program
main( int argc, char *argv[ ] ) {
glutInit( &argc, argv ); InitGraphics( ); InitLists( );
InitCL( );
Reset( ); InitGlui( ); glutMainLoop( ); return 0;
Computer Graphics
mjb March 27, 2021

GLEW the GL Extension Wrangler
#ifdef WIN32
GLenum err = glewInit( ); if( err != GLEW_OK )
fprintf( stderr, glewInit Error
); #endif
This must wait to be called until after a graphics window is open !
Why? Because creating the window is what builds the graphics context.
Computer Graphics
mjb March 27, 2021

Setting up OpenCL:
Querying the Existence of an OpenCL Extension
void InitCL( ) {
status = clGetDeviceIDs( Platform, CL_DEVICE_TYPE_GPU, 1, &Device, NULL );
PrintCLError( status, clGetDeviceIDs: );
// since this is an opengl interoperability program,
// check if the opengl sharing extension is supported
// (no point going on if it isnt):
// (we need the Device in order to ask, so we cant do it any sooner than right here)
if( IsCLExtensionSupported( cl_khr_gl_sharing ) ) {
fprintf( stderr, cl_khr_gl_sharing is supported.
);
fprintf( stderr, cl_khr_gl_sharing is not supported sorry.
);
Computer Graphics
mjb March 27, 2021

Querying the Existence of an OpenCL Extension
IsCLExtensionSupported( const char *extension ) {
// see if the extension is bogus:
if( extension == NULL || extension[0] == ) return false;
char * where = (char *) strchr( extension, ); if( where != NULL )
return false;
// get the full list of extensions:
size_t extensionSize;
clGetDeviceInfo( Device, CL_DEVICE_EXTENSIONS, 0, NULL, &extensionSize );
char *extensions = new char [ extensionSize ];
clGetDeviceInfo( Device, CL_DEVICE_EXTENSIONS, extensionSize, extensions, NULL );
for( char * start = extensions ; ; ) {
where = (char *) strstr( (const char *) start, extension ); if( where == 0 )
delete [ ] extensions;
return false; }
char * terminator = where + strlen(extension); // points to what should be the separator
if( *terminator == || *terminator == || *terminator == r || *terminator ==
) {
delete [ ] extensions;
return true; }
start = terminator;
Computer Graphics
mjb March 27, 2021

Setting up OpenCL: The Interoperability Context
void InitCL( ) {
// get the platform id:
status = clGetPlatformIDs( 1, &Platform, NULL ); PrintCLError( status, clGetPlatformIDs: );
// get the device id:
status = clGetDeviceIDs( Platform, CL_DEVICE_TYPE_GPU, 1, &Device, NULL ); PrintCLError( status, clGetDeviceIDs: );
// 3. create a special opencl context based on the opengl context:
cl_context_properties props[ ] = {
CL_GL_CONTEXT_KHR, CL_WGL_HDC_KHR, CL_CONTEXT_PLATFORM, 0
cl_context Context = clCreateContext( props, 1, &Device, NULL, NULL, &status ); PrintCLError( status, clCreateContext: );
(cl_context_properties) wglGetCurrentContext( ), (cl_context_properties) wglGetCurrentDC( ), (cl_context_properties) Platform,
Computer Graphics
mjb March 27, 2021

Setting up OpenCL:
The Interoperability Context is Different for each OS (oh, good)
For Windows:
cl_context_properties props[ ] = {
CL_GL_CONTEXT_KHR, CL_WGL_HDC_KHR, CL_CONTEXT_PLATFORM, 0
(cl_context_properties) wglGetCurrentContext( ), (cl_context_properties) wglGetCurrentDC( ), (cl_context_properties) Platform,
cl_context Context = clCreateContext( props, 1, &Device, NULL, NULL, &status );
For Linux:
cl_context_properties props[ ] = {
CL_GL_CONTEXT_KHR, CL_GLX_DISPLAY_KHR, CL_CONTEXT_PLATFORM, 0
(cl_context_properties) glXGetCurrentContext( ), (cl_context_properties) glXGetCurrentDisplay( ), (cl_context_properties) Platform,
cl_context Context = clCreateContext( props, 1, &Device, NULL, NULL, &status );
For Apple:
cl_context_properties props[ ] = {
CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, (cl_context_properties) kCGLShareGroup,
cl_context Context = clCreateContext( props, 0, 0, NULL, NULL, &status );
Computer Graphics
mjb March 27, 2021

Setting up OpenCL
hVel stands for host Velocities hPobj stands for host Points object hCobj stands for host Colors object
void InitCL( ) {
// create the velocity array and the opengl vertex array buffer and color array buffer:
delete [ ] hVel;
hVel = new struct xyzw [ NUM_PARTICLES ];
glGenBuffers( 1, &hPobj );
glBindBuffer( GL_ARRAY_BUFFER, hPobj );
glBufferData( GL_ARRAY_BUFFER, 4 * NUM_PARTICLES * sizeof(float), NULL, GL_STATIC_DRAW );
glGenBuffers( 1, &hCobj );
glBindBuffer( GL_ARRAY_BUFFER, hCobj );
glBufferData( GL_ARRAY_BUFFER, 4 * NUM_PARTICLES * sizeof(float), NULL, GL_STATIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER, 0 ); // unbind the buffer // fill those arrays and buffers:
ResetParticles( );
Computer Graphics
mjb March 27, 2021

Setting the Initial Particle Parameters, I
unsigned int Seed;
void ResetParticles( )
glBindBuffer( GL_ARRAY_BUFFER, hPobj );
struct xyzw *points = (struct xyzw *) glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY ); for( int i = 0; i < NUM_PARTICLES; i++ )points[ i ].x = Ranf( &Seed, XMIN, XMAX ); points[ i ].y = Ranf( &Seed, YMIN, YMAX ); points[ i ].z = Ranf( &Seed, ZMIN, ZMAX ); points[ i ].w = 1.;glUnmapBuffer( GL_ARRAY_BUFFER );glBindBuffer( GL_ARRAY_BUFFER, hCobj );struct rgba *colors = (struct rgba *) glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY ); for( int i = 0; i < NUM_PARTICLES; i++ )colors[ i ].r = Ranf( &Seed, 0., 1. ); colors[ i ].g = Ranf( &Seed, 0., 1. ); colors[ i ].b = Ranf( &Seed, 0., 1. ); colors[ i ].a = 1.;glUnmapBuffer( GL_ARRAY_BUFFER ); Computer Graphicsmjb March 27, 2021 Setting the Initial Particle Parameters, IIfor( int i = 0; i < NUM_PARTICLES; i++ ) {hVel[ i ].x = Ranf( &Seed, VMIN, VMAX ); hVel[ i ].y = Ranf( &Seed, 0. , VMAX ); hVel[ i ].z = Ranf( &Seed, VMIN, VMAX ); hVel[ i ].w = 0.; Computer Graphicsmjb March 27, 2021 Setting-up the Device-Side Buffers void InitCL( ) {// 5. create the opencl version of the velocity array:dVel = clCreateBuffer( Context, CL_MEM_READ_WRITE, 4*sizeof(float)*NUM_PARTICLES, NULL, &status ); PrintCLError( status, “clCreateBuffer: ” );// 6. write the data from the host buffers to the device buffers:status = clEnqueueWriteBuffer( CmdQueue, dVel, CL_FALSE, 0, 4*sizeof(float)*NUM_PARTICLES, hVel, 0, NULL, NULL ); PrintCLError( status, “clEneueueWriteBuffer: ” );// 5. create the opencl version of the opengl buffers:dPobj = clCreateFromGLBuffer( Context, CL_MEM_READ_WRITE, hPobj, &status ); PrintCLError( status, “clCreateFromGLBuffer (1)” );dCobj = clCreateFromGLBuffer( Context, CL_MEM_READ_WRITE , hCobj, &status ); PrintCLError( status, “clCreateFromGLBuffer (2)” );Note: you dont need an OpenGL-accessible buffer for the velocities. Velocities arent needed for drawing. Velocities are only needed to update point positions. The velocity buffer can just be done internally to OpenCL.Computer Graphicsmjb March 27, 2021 This is how OpenCL and OpenGL Share the Same Memory Buffer dPobj = clCreateFromGLBuffer( Context, CL_MEM_READ_WRITE, hPobj, &status ); PrintCLError( status, “clCreateFromGLBuffer (1)” ); Step #1: OpenGL creates the buffer on the GPUStep #2: OpenCL is told about it and creates a device pointer to the already-filled memory, just as if you had called clCreateBuffer( ) and clEnqueu CS: assignmentchef QQ: 1823890830 Email: [email protected]

Reviews

There are no reviews yet.

Only logged in customers who have purchased this product may leave a review.

Shopping Cart
[SOLVED] CS WIN32
$25