代写代考 WIN32

This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License
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

Copyright By PowCoder代写 加微信 powcoder

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
Computer Graphics
Also, see the video at:

opencl.opengl.vbo.pptx
mjb – March 27, 2021
OpenCL / OpenGL Vertex Buffer Interoperability: A Particle System Case Study
Some of the Inner Workings of OpenGL:
Feel Free to Detour Right to Slide #24 if You Don’t 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
Here’s What OpenGL Has Been Moving To: Vertex Buffer Objects
GLfloat CubeColors[ ][3] = {
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.}
{ 0., 0., 0. }, { 1., 0., 0. }, { 0., 1., 0. }, { 1., 1., 0. }, { 0., 0., 1. }, { 1., 0., 1. }, { 0., 1., 1. }, { 1., 1., 1. },
GLuint CubeIndices[ ][4] = {
Computer Graphics
mjb – March 27, 2021
{ 0, 2, 3, 1 }, { 4, 5, 7, 6 }, { 1, 3, 7, 5 }, { 0, 4, 6, 2 }, { 2, 6, 7, 3 }, { 0, 1, 5, 4 }
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
Array Buffer Display
Texture0 Texture1
Context Dest. Lighting Transformation
If we were implementing the OpenGL state as a C++ structure (which we’re 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 doesn’t 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 It’s very fast to re-bind a different vertex buffer. It
amounts to just changing a pointer.
glBindBuffer( GL_ARRAY_BUFFER, buf );
Array Buffer
Array Buffer Display
Texture0 Texture1
Context Dest. Lighting 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 findtobemorevisuallypleasing)anOpenGLobjecttotheContext. Youcanthen assign characteristics, and they will “flow” through the Context into the object.
glBindBuffer( GL_ARRAY_BUFFER, buf );
glBufferData( GL_ARRAY_BUFFER, numBytes, data, usage );
Vertex Buffer Object
Think of it as happening this way:
Computer Graphics
mjb – March 27, 2021
Context.ArrayBuffer.memStart = CopyToGpuMemory( data, numBytes ); Context.ArrayBuffer.memSize = numBytes;
Array Buffer
Element Array Buffer
Lighting Transformation
Texture0 Texture1
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
Computer Graphics
mjb – March 27, 2021
Array Buffer
Element Array Buffer
Lighting Transformation
glBindBuffer( GL_ARRAY_BUFFER, buf );
Think of it as happening this way:
float *data = Context.ArrayBuffer.memStart;
Texture0 Texture1
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 13
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 15
Computer Graphics
mjb – March 27, 2021
GLfloat Vertices[ ][3] = {
{1., 2., 3.}, {4., 5., 6.}, …
int numVertices = sizeof(Vertices) / ( 3*sizeof(GLfloat) );
Vertex Buffers: Step #2 – Create the Buffers and Fill Them 16
Computer Graphics
mjb – March 27, 2021
glGenBuffers( 1, &buf );
glBindBuffer( GL_ARRAY_BUFFER, buf );
glBufferData( GL_ARRAY_BUFFER, 3*sizeof(GLfloat)*numVertices, Vertices, GL_STATIC_DRAW );
Vertex Buffers: Step #3 – Activate the Array Types That You 17 glEnableClientState( type )
where type can be any of:
• 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:
GL_VERTEX_ARRAY GL_COLOR_ARRAY GL_NORMAL_ARRAY GL_TEXTURE_COORD_ARRAY
glDisableClientState( type )
Computer Graphics
mjb – March 27, 2021
Vertex Buffers: Step #4 – To Draw, First Bind the Buffers 18
glBindBuffer( GL_ARRAY_BUFFER, buf );
Vertex Buffer Object
Transformation
Computer Graphics
mjb – March 27, 2021
Array Buffer
Element Array Buffer
Lighting Transformation
Texture0 Texture1

Vertex Buffers: Step #5 – Specify the Data
size is the spatial dimension, and can be: 2, 3, or 4 type can be:
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);
vs. Vertex Data Color Data Vertex Data Color Data Vertex Data Color Data
GL_SHORT GL_INT GL_FLOAT GL_DOUBLE
stride is the byte offset between consecutive entries in the array (0 means tightly packed)
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.
Computer Graphics
mjb – March 27, 2021
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));
glVertexPointer( 3, GL_FLOAT, 6*sizeof(GLfloat), 0 ); glColorPointer( 3, GL_FLOAT, 6*sizeof(GLfloat), 3*sizeof(GLfloat) );
The Data Types in a vertex buffer object can be stored either as “packed” or “interleaved”
gl*Pointer( size, type, stride, offset);
Interleaved:
Computer Graphics
Vertex Data Color Data Vertex Data Color Data Vertex Data Color Data
mjb – March 27, 2021
Vertex Buffers: Step #6 – Specify the Connections 21 25
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 22 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 doesn’t 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: glUnMapBuffer( GL_ARRAY_BUFFER );
Computer Graphics
mjb – March 27, 2021
Computer Graphics
We Now Pickup with the OpenCL Stuff 23
mjb – March 27, 2021
Computer Graphics
We Now Pickup with the OpenCL Stuff 24
mjb – March 27, 2021

Either OpenGL or OpenCL can use the Vertex Buffer at a time, but not both: 25 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 26
Computer Graphics
mjb – March 27, 2021
#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”
Structures We to Fill the Vertex Buffers 27
// 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 28
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 29
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 30
#ifdef WIN32
GLenum err = glewInit( ); if( err != GLEW_OK )
fprintf( stderr, “glewInit Error\n” ); #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: 31 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 isn’t):
// (we need the Device in order to ask, so we can’t do it any sooner than right here)
if( IsCLExtensionSupported( “cl_khr_gl_sharing” ) ) {
fprintf( stderr, “cl_khr_gl_sharing is supported.\n” );
fprintf( stderr, “cl_khr_gl_sharing is not supported — sorry.\n” );
Computer Graphics
mjb – March 27, 2021
Querying the Existence of an OpenCL Extension 32
IsCLExtensionSupported( const char *extension ) {
// see if the extension is bogus:
if( extension == NULL || extension[0] == ‘\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 == ‘\0’ || *terminator == ‘\r’ || *terminator == ‘\n’ ) {
delete [ ] extensions;
return true; }
start = terminator;
Computer Graphics
mjb – March 27, 2021
Setting up OpenCL: The Interoperability Context 33
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: 34 The Interoperability Context is Different for each OS (oh, good…)
For Windows:
cl_context_properties props[ ] = {
CL_GL_CONTEXT_KHR, CL_W GL_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 35
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( );
”hVel” stands for “host Velocities’” “hPobj” stands for “host Points object” “hCobj” stands for “host Colors object”
Computer Graphics
mjb – March 27, 2021
unsigned int Seed; …
void ResetParticles( )
Setting the Initial Particle Parameters, I 36
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 Graphi.cs. . mjb – March 27, 2021 Setting the Initial Particle Parameters, II 37 for( 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 Graphics mjb – March 27, 2021 Setting-up the Device-Side Buffers 38 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 don’t need an OpenGL-accessible buffer for the velocities. Velocities aren’t needed for drawing. Velocities are only needed to update point positions. The velocity buffer can just be done internally to OpenCL. Computer Graphics mjb – March 27, 2021 This is how OpenCL and OpenGL Share the Same Memory Buffer 39 dPobj = clCreateFromGLBuffer( Context, CL_MEM_READ_WRITE, hPobj, &status ); PrintCLError( status, "clCreateFromGLBuffer (1)" ); Step #1: OpenGL creates the buffer on the GPU Step #2: OpenCL is told about it and creates a device pointer to the already-filled memory, just as if you had 程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com