Rendering issue with different computers - c++

So i am making a short of tower defense game. I shared a build with them so i can check if everything performs as it should on another host.
And what actually happens is that while everything renders perfectly on my side (both on my mac/xcode + windows/visual studio 2012), on my friend's side it seems like the geometry is messed up. Each object on my screen is represented by a VBO which i use every time to render to different locations. But it seems like my VBOs have all the geometry imported from all models. (Hence the Tower with the tree on the side.)
Here's the result:
(My computer)(My friend's computer)
As by now i've managed to debug this issue up to a certain point. I can tell it's not the way i'm importing my models because i'm creating a debug.txt file with all the vectors before i send them to gpu as VBOs and on both computers they output the same values. So i their vectors are not getting messed up by memory issues or anything like that. So i am thinking maybe it is the way i am setting up or rendering my VBOs
What strikes me the most though is why things work on my computer while they are not on my friends computer. One difference i know for sure is that my computer is a developer station(whatever this means) while my friend's computer is not.
This is my VBO loading function and my VBO drawing function:
I use glfw to create my window and context and include glew headers to enable some of the newer opengl functions.
void G4::Renderer::LoadObject(
G4::TILE_TYPES aType,
std::vector<float> &v_data,
std::vector<float> &n_data,
std::vector<float> &t_data,
float scale,
bool has_texture,
unsigned int texture_id
)
{
unsigned int vertices_id, vertices_size, normals_id, texturecoordinates_id;
vertices_size = static_cast<unsigned int>(v_data.size());
glGenBuffers(1, &vertices_id);
glGenBuffers(1, &normals_id);
//::->Vertex array buffer upload.
glBindBuffer(GL_ARRAY_BUFFER, vertices_id);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*v_data.size(), &v_data.front(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//::->Normal Array buffer upload.
glBindBuffer(GL_ARRAY_BUFFER, normals_id);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*n_data.size(), &n_data.front(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
if (has_texture)
{
glGenBuffers(1, &texturecoordinates_id);
glBindBuffer(GL_ARRAY_BUFFER, texturecoordinates_id);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*t_data.size(), &(t_data[0]), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
this->vbos[aType].Update(vertices_id, vertices_size, normals_id, texture_id, texturecoordinates_id, scale, has_texture);
}
Draw code:
void G4::Renderer::DrawUnit(G4::VBO aVBO, bool drawWithColor, float r, float g, float b, float a)
{
bool model_has_texture = aVBO.HasTexture();
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
if (model_has_texture && !drawWithColor) {
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
}
if (drawWithColor)
{
glColor4f(r, g, b, a);
}
glScalef(aVBO.GetScaleValue(), aVBO.GetScaleValue(), aVBO.GetScaleValue());
glBindBuffer(GL_ARRAY_BUFFER, aVBO.GetVerticesID());
glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, aVBO.GetNormalsID());
glNormalPointer(GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
if (model_has_texture && !drawWithColor)
{
glBindTexture(GL_TEXTURE_2D, aVBO.GetTextureID());
glBindBuffer(GL_ARRAY_BUFFER, aVBO.GetTextureCoordsID());
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
glDrawArrays(GL_TRIANGLES, 0, aVBO.GetVerticesSize());
if (model_has_texture && !drawWithColor) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
I'm out of ideas i hope someone can direct me on how to debug this any further.

The OpenGL spec. does not specify the exact behaviour that should occur when you issue a draw call with more vertices than your buffer stores. The reason this may work correctly on one machine and not on another comes down to implementation. Each vendor is free to do whatever they want if this situation occurs, so the render artifacts might show up on AMD hardware but not at all on nVIDIA or Intel. Making matters worse, there is actually no error state generated by a call to glDrawArrays (...) when it is asked to draw too many vertices. You definitely need to test your software on hardware sourced from multiple vendors to catch these sorts of errors; who manufactures the GPU in your computer, and the driver version, is just as important as the operating system and compiler.
Nevertheless there are ways to catch these silly mistakes. gDEBugger is one, and there is also a new OpenGL extension I will discuss below. I prefer to use the new extension because in my experience, in addition to deprecated API calls and errors (which gDEBugger can be configured to monitor), the extension can also warn you for using inefficiently aligned data structures and various other portability and performance issues.
I wanted to add some code I use to use OpenGL Debug Output in my software, since this is an example of an errant behaviour that does not actually generate an error that you can catch with glGetError (...). Sometimes, you can catch these mistakes with Debug Output (though, I just tested it and this is not one of those situations). You will need an OpenGL Debug Context for this to work (the process of setting this up is highly platform dependent), but it is a context flag just like forward/backward compatible and core (glfw should make this easy for you).
Automatic breakpoint macro for x86 platforms
// Breakpoints that should ALWAYS trigger (EVEN IN RELEASE BUILDS) [x86]!
#ifdef _MSC_VER
# define eTB_CriticalBreakPoint() if (IsDebuggerPresent ()) __debugbreak ();
#else
# define eTB_CriticalBreakPoint() asm (" int $3");
#endif
Enable OpenGL Debug Output (requires a Debug Context and a relatively recent driver, OpenGL 4.x era)
// SUPER VERBOSE DEBUGGING!
if (glDebugMessageControlARB != NULL) {
glEnable (GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
glDebugMessageControlARB (GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
glDebugMessageCallbackARB ((GLDEBUGPROCARB)ETB_GL_ERROR_CALLBACK, NULL);
}
Some important utility functions to replace enumerant values with more meaningful text
const char*
ETB_GL_DEBUG_SOURCE_STR (GLenum source)
{
static const char* sources [] = {
"API", "Window System", "Shader Compiler", "Third Party", "Application",
"Other", "Unknown"
};
int str_idx =
min ( source - GL_DEBUG_SOURCE_API,
sizeof (sources) / sizeof (const char *) );
return sources [str_idx];
}
const char*
ETB_GL_DEBUG_TYPE_STR (GLenum type)
{
static const char* types [] = {
"Error", "Deprecated Behavior", "Undefined Behavior", "Portability",
"Performance", "Other", "Unknown"
};
int str_idx =
min ( type - GL_DEBUG_TYPE_ERROR,
sizeof (types) / sizeof (const char *) );
return types [str_idx];
}
const char*
ETB_GL_DEBUG_SEVERITY_STR (GLenum severity)
{
static const char* severities [] = {
"High", "Medium", "Low", "Unknown"
};
int str_idx =
min ( severity - GL_DEBUG_SEVERITY_HIGH,
sizeof (severities) / sizeof (const char *) );
return severities [str_idx];
}
DWORD
ETB_GL_DEBUG_SEVERITY_COLOR (GLenum severity)
{
static DWORD severities [] = {
0xff0000ff, // High (Red)
0xff00ffff, // Med (Yellow)
0xff00ff00, // Low (Green)
0xffffffff // ??? (White)
};
int col_idx =
min ( severity - GL_DEBUG_SEVERITY_HIGH,
sizeof (severities) / sizeof (DWORD) );
return severities [col_idx];
}
My Debug Output Callback (somewhat messy, because it prints each field in a different color in my software)
void
ETB_GL_ERROR_CALLBACK (GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
GLvoid* userParam)
{
eTB_ColorPrintf (0xff00ffff, "OpenGL Error:\n");
eTB_ColorPrintf (0xff808080, "=============\n");
eTB_ColorPrintf (0xff6060ff, " Object ID: ");
eTB_ColorPrintf (0xff0080ff, "%d\n", id);
eTB_ColorPrintf (0xff60ff60, " Severity: ");
eTB_ColorPrintf ( ETB_GL_DEBUG_SEVERITY_COLOR (severity),
"%s\n",
ETB_GL_DEBUG_SEVERITY_STR (severity) );
eTB_ColorPrintf (0xffddff80, " Type: ");
eTB_ColorPrintf (0xffccaa80, "%s\n", ETB_GL_DEBUG_TYPE_STR (type));
eTB_ColorPrintf (0xffddff80, " Source: ");
eTB_ColorPrintf (0xffccaa80, "%s\n", ETB_GL_DEBUG_SOURCE_STR (source));
eTB_ColorPrintf (0xffff6060, " Message: ");
eTB_ColorPrintf (0xff0000ff, "%s\n\n", message);
// Force the console to flush its contents before executing a breakpoint
eTB_FlushConsole ();
// Trigger a breakpoint in gDEBugger...
glFinish ();
// Trigger a breakpoint in traditional debuggers...
eTB_CriticalBreakPoint ();
}
Since I could not actually get your situation to trigger a debug output event, I figured I would at least show an example of an event I was able to trigger. This is not an error that you can catch with glGetError (...), or an error at all for that matter. But it is certainly a draw call issue that you might be completely oblivious to for the duration of your project without using this extension :)
OpenGL Error:
=============
Object ID: 102
Severity: Medium
Type: Performance
Source: API
Message: glDrawElements uses element index type 'GL_UNSIGNED_BYTE' that is not optimal for the current hardware configuration; consider using 'GL_UNSIGNED_SHORT' instead.

After further debugging sessions with my friends and much tryouts i managed to find the problem. This took me two solid days to figure out and really it was just a silly mistake.
glDrawArrays(GL_TRIANGLES, 0, aVBO.GetVerticesSize());
The above code does not get the vertices size (as points) but as a total number of floats stored there. So everything is multiplied by 3. Adding a /3 solved it.
So i assume since the total points where multiplied by 3 times the vbo "stole" data from other vbos stored on the gpu. (Hence the tree model stack to my tower).
What i can't figure out yet though, and would like an answer on that, is why on my computer everything rendered fine but not on other computers. As i state in my original question a hint would be that my computer is actually a developer station while my friend's not.
Anyone who is kind enough to explain why this effect doesn't reproduce on me i will gladly accept his answer as a solution to my problem.
Thank you

Related

Vulkan VMA buffer is empty

I have been trying to implement Vulkan Memory Allocator in my application, but all I get is a blank screen. I use deferred and HDR pipeline and I allocate all my attachments using VMA. I tried outputting solid color in the fragment shader and it worked, so I suppose that the problem is that my vertex and index buffers are empty. I use staging buffer to copy data into vertex buffer. I fill the staging buffer like this:
void* data;
vmaMapMemory(_allocator, stagingAllocation, &data);
memcpy(data, bufferData, bufferSize);
vmaUnmapMemory(_allocator, stagingAllocation);
I also tried using vertex buffer without staging buffer and setting the flags
allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;
and copying data directly to vertex buffer with
memcpy(allocInfo.pMappedData, bufferData, bufferSize);
but that does not seem to work either.
Full code:
VkBuffer stagingBuffer;
VkBuffer vertexBuffer;
VmaAllocation stagingAllocation = createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY, stagingBuffer);
void* data;
vmaMapMemory(_allocator, stagingAllocation, &data);
memcpy(data, bufferData, bufferSize);
vmaUnmapMemory(_allocator, stagingAllocation);
VmaAllocation allocation = createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY, vertexBuffer);
copyBuffer(stagingBuffer, vertexBuffer, bufferSize);
vmaDestroyBuffer(_allocator, stagingBuffer, stagingAllocation);
createBuffer function:
VmaAllocation createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VmaMemoryUsage memoryUsage, VkBuffer &buffer) {
VkBufferCreateInfo bufferInfo{};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = size;
bufferInfo.usage = usage;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VmaAllocationCreateInfo allocCreateInfo = {};
allocCreateInfo.usage = memoryUsage;
VmaAllocation allocation;
if (vmaCreateBuffer(_allocation, &bufferInfo, & allocCreateInfo, &buffer, &allocation, nullptr) != VK_SUCCESS) {
throw std::runtime_error("Failed to create buffer");
}
return allocation;
}
If I set allocCreateInfo.flags to 0, I get weird flickering.
I have looked at many examples and all of them seem to be similar to my code.
I should also mention that it was working before I started using VMA and I have only modified the code I listed (plus the same code for image creation, but that seems to work fine).
I am on MacOS, Vulkan 1.2.
Any help would be greatly appreciated.
EDIT:
So after some hours of debugging, I figured it out. The problem was not in my vertex buffers, but rather in uniform buffers. I used flag VMA_MEMORY_USAGE_CPU_TO_GPU. After setting it to VMA_MEMORY_USAGE_CPU_ONLY, it started to work. This is only a temporary solution, since I do not want to store all my uniform buffers in cpu memory. If somebody knows what is wrong, please let me know.
Thank you
EDIT 2:
So turns out that VMA does not use VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT or VK_MEMORY_PROPERTY_HOST_COHERENT_BIT automatically when you set usage to be VMA_MEMORY_USAGE_CPU_TO_GPU. You need to include these flags in allocCreateInfo.requiredFlags. After doing this it works fine. However, I could not find this in the docs, so it was quite hard to debug.

How I can get my total GPU memory using Qt's native OpenGL?

I'm trying to get the total amount of GPU memory from my video card using native Qt's OpenGL, I have tried hundred of methods, but none do work.
This is what I have at the moment:
QOpenGLContext context;
context.create();
QOffscreenSurface surface;
surface.setFormat(context.format());
surface.create();
QOpenGLFunctions func;
context.makeCurrent(&surface);
func.initializeOpenGLFunctions();
GLint total_mem_kb = 0;
func.glGetIntegerv(GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX,&total_mem_kb);
qDebug()<<total_mem_kb;
The problem is that the variable total_mem_kb is always 0, It does not get the value inside of glGetIntegerv. By running this code I get 0. What can be the problem? Can you please give me a hint?
First an foremost check if the NVX_gpu_memory_info extension is supported.
Note that the extension requires OpenGL 2.0 at least.
GLint count;
glGetIntegerv(GL_NUM_EXTENSIONS, &count);
for (GLint i = 0; i < count; ++i)
{
const char *extension = (const char*)glGetStringi(GL_EXTENSIONS, i);
if (!strcmp(extension, "GL_NVX_gpu_memory_info"))
printf("%d: %s\n", i, extension);
}
I know you just said that you have an Nvidia graphics card, but this doesn't by default guarantee support. Additionally if you have an integrated graphics card then make sure you are actually using your dedicated graphics card.
If you have an Nvidia GeForce graphics card, then then the following should result in something along the lines of "Nvidia" and "GeForce".
glGetString(GL_VENDOR);
glGetString(GL_RENDERER);
If it returns anything but "Nvidia" then you need to open your Nvidia Control Panel and set the preferred graphics card to your Nvidia graphics card.
After you've verified it being the Nvidia graphics card and that the extension is supported. Then you can try getting the total and current available memory:
GLint totalMemoryKb = 0;
glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &totalMemoryKb);
GLint currentMemoryKb = 0;
glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &currentMemoryKb);
I would also like to point out that the NVX_gpu_memory_info extension defines it as:
GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX
and not
GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX
Note the MEMORY vs MEM difference.
So suspecting you've defined GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX yourself or leveraging something else that has defined it. That tells it could be wrongly defined or referring to something else.
I use the following:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
LONG __stdcall glxGpuTotalMemory()
{
GLint total_mem_kb = 0;
glGetIntegerv(GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX, &total_mem_kb);
if (total_mem_kb == 0 && wglGetGPUIDsAMD)
{
UINT n = wglGetGPUIDsAMD(0, 0);
UINT *ids = new UINT[n];
size_t total_mem_mb = 0;
wglGetGPUIDsAMD(n, ids);
wglGetGPUInfoAMD(ids[0], WGL_GPU_RAM_AMD, GL_UNSIGNED_INT, sizeof(size_t), &total_mem_mb);
total_mem_kb = total_mem_mb * 1024;
}
return total_mem_kb;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
LONG __stdcall glxGpuAvailMemory()
{
GLint cur_avail_mem_kb = 0;
glGetIntegerv(GL_GPU_MEM_INFO_CURRENT_AVAILABLE_MEM_NVX, &cur_avail_mem_kb);
if (cur_avail_mem_kb == 0 && wglGetGPUIDsAMD)
{
glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, &cur_avail_mem_kb);
}
return cur_avail_mem_kb;
}

glVertexAttribPointer raising impossible GL_INVALID_OPERATION?

I have narrowed down the error to this OpenGL call:
glVertexAttribPointer(var.vertex, 4, GL_FLOAT, GL_FALSE, 0, 0);
there are no errors before it, and there is a GL_INVALID_OPERATION error after it.
The output to my console is:
Error in Shader.cpp : bindMesh : 294
OpenGL Error: Invalid Operation
(0x502)
Bound Buffer: 1
var.vertex = 1
According to this, the only GL_INVALID_OPERATION condition that could apply is a bound buffer ID of 0. But the bound buffer ID is 1.
I'm checking (and printing) the error with:
printErrors();
int i = 0;
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &i);
printf("\tBound Buffer: %i\n", i);
printf("\tvar.vertex = %i\n", var.vertex);
where printErrors() is defined as
void PrintErrors(const char* file, const char* func, int line);
#define printErrors() PrintErrors(__BASE_FILE__,__func__,__LINE__)
void PrintErrors(const char* file, const char* func, int line)
{
const char* errors[] = {
"OpenGL Error: Invalid Enumeration\n",
"OpenGL Error: Invalid Value\n",
"OpenGL Error: Invalid Operation\n",
"OpenGL Error: Invalid Frame-Buffer Operation\n",
"OpenGL Error: Out of Memory\n",
"OpenGL Error: Stack Underflow\n",
"OpenGL Error: Stack Overflow\n",
};
uint32 i = glGetError();
while (i != GL_NO_ERROR)
{
printf("Error in %s : %s : %i\n\t%s\t(0x%x)\n", file, func, line, errors[i - GL_INVALID_ENUM], i);
i = glGetError();
}
}
What's going wrong?
Edit:
var.vertex is found with:
var.vertex = glGetAttribLocation(programID, "Vertex");
and there is a check to ensure that var.vertex was found in the bound shader by an if-statement:
if (var.vertex != INVALID_SHADER_VARIABLE) // INVALID_SHADER_VARIABLE = 0xFFFFFFFF (-1 if it where a signed int)
{
glBindBuffer(...);
glBuffferData(...);
glEnableVertexAttribArray(var.vertex);
glVertexAttribPointer(var.vertex, 4, GL_FLOAT, GL_FALSE, 0, 0);
}
You must have a non-zero Vertex Array Object bound in an OpenGL 3.1 context without the extension GL_ARB_compatibility or a core profile context. This is one of the hidden conditions that will generate a GL_INVALID_OPERATION whenever you attempt to do anything related to vertex arrays (e.g. draw, setup vertex pointers, etc.)
The good news is this is a trivial issue to fix.
At minimum, all you need to do is generate (glGenVertexArrays (...)) and bind (glBindVertexArray (...)) a vertex array object when you initialize your program.

CL_OUT_OF_RESOURCES on clEnqueueAcquireGLObjects

After rearranging some OpenCL/GL interop code it stopped working and gave the error in the title.
I already read many threads that discussed this issue and blamed the (nvidia) driver for it. But as the code ran before this should not be my problem.
Code
As I already said I have too much code to post all of it. Also I am not able to reproduce the behaviour in minimal examples so far, so I am going to describe most of the program in pseudo code and parts in excerpts from my real code.
I use Qt, therefore following functions are all members of my subclass of QGLWidget:
void initializeGL()
{
glewInit();
cl::Platform::get(&clPlatforms);
cl_context_properties props[] = {
CL_GL_CONTEXT_KHR, (cl_context_properties)glXGetCurrentContext(),
CL_GLX_DISPLAY_KHR, (cl_context_properties)glXGetCurrentDisplay(),
CL_CONTEXT_PLATFORM, (cl_context_properties)clPlatforms[0](),
0
};
clContext = cl::Context(CL_DEVICE_TYPE_GPU, props, cl_notify, &err);
std::vector<cl::Device> devices = clContext.getInfo<CL_CONTEXT_DEVICES>();
clDevice = devices[0];
clQueue = cl::CommandQueue(clContext, clDevice, 0, 0);
clProgram = cl::Program(context, sources);
clProgram.build();
clKernel = cl::Kernel(clProgram, "main");
glGenBuffers(1, &vbo);
glBindBuffers(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, bufferSize, buffer, GL_DYNAMIC_DRAW);
glBindBuffers(GL_ARRAY_BUFFER, 0);
vboBuffer = cl::BufferGL(clContext, CL_MEM_READ_WRITE, vbo);
clKernel.setArg(0, vboBuffer);
}
void paintGL()
{
simulate();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//camera transformations ...
glEnable(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexPointer(3, GL_FLOAT, sizeof(cl_float3), 0);
glDrawElements(GL_TRIANGLES, 3 * numTriangles, GL_UNSIGNED_INT, triangleIdicesArray);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void simulate()
{
std::vector<cl::Memory> sharedObjects;
sharedObjects.push_back(vboBuffer);
clQueue.enqueueAcquireGLObjects(&sharedObjects); //this triggers the error
clQueue.enqueNDRangKernel(clKernel, cl::NullRange, cl::NDRangle(numVertices), cl::NullRange);
clQueue.enqueueReleaseGLObjects(&sharedObjects);
}
Some further investigation about glEnqueueAcquireGLObjects turned up (in the notes section):
Prior to calling clEnqueueAcquireGLObjects, the application must ensure that any pending GL operations which access the objects specified in mem_objects have completed. This may be accomplished portably by issuing and waiting for completion of a glFinish command on all GL contexts with pending references to these objects.
Adding a finish on the OpenCL command queue before and after the acquire/release got me rid of these errors.
As with other errors I find the error code misleading and the notify function did not add any valuable information (it said the same).

OpenGL VBO not updating properly

I am having an OpenGL VBO problem. I downloaded the old VBO example called Lesson45 from NeHe and I modified it to check something.
My end result is to create about 9 tiles, one of them being the origin. Then as the player moves on the screen, the top/bottom rows/columns update the data. But for now I want something basic:
I create one VBO and then I want to update the data in another thread. While the data is being uploaded, I do not want to draw the VBO because that would cause problems.
Here I create the VBO:
glGenBuffersARB( 1, &m_nVBOVertices );
glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_nVBOVertices);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, m_nVertexCount*3*sizeof(float), m_pVertices, GL_DYNAMIC_DRAW_ARB);
I create a thread, I set up an OpenGL context, I share lists. Then I process the data, when the user presses "R" on the keyboard:
while(TerrainThreadRun)
{
//look for R
if(window.keys->keyDown[82] == TRUE && keyactivated == false)
{
keyactivated = true;
window.keys->keyDown[82] = FALSE;
}
if(keyactivated)
{
for(int i = 0; i < g_pMesh->m_nVertexCount; i++)
{
g_pMesh->m_pVertices[i].y = 800.0f;
}
while(!wglMakeCurrent(window.hDCThread,window.hRCThread))//This was removed
Sleep(5);//This was removed
glBindBufferARB(GL_ARRAY_BUFFER_ARB, g_pMesh->m_nVBOVertices);
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, g_pMesh->m_nVertexCount*3*sizeof(float), g_pMesh->m_pVertices);
keyactivated = false;
}
}
To draw the data:
if(!keyactivated)
{
glEnableClientState( GL_VERTEX_ARRAY );
glBindBufferARB(GL_ARRAY_BUFFER_ARB, g_pMesh->m_nVBOVertices);
glVertexPointer(3, GL_FLOAT, 0, (char*)NULL);
glDrawArrays(GL_TRIANGLES, 0, g_pMesh->m_nVertexCount);
glDisableClientState(GL_VERTEX_ARRAY);
}
I know that using ARB extensions is not recommended, but this is just for a quick basic example.
The problem is that when I first press "R", the data does not get updated. The VBO draws the same. The second time that I press "R", it updates the data. What can I do to force the draw. Am I doing something wrong?
Does the data need to be forced to the video card? Am I missing something?
Update: I looked over my code and now I use wglMakeCurrent only once, when the context is initialized. In the thread, I use it after sharing the lists and on the main thread as soon as the lists are shared, like this:
window->hRC = wglCreateContext (window->hDC);
if (window->hRC ==0)
{
// Failed
}
TerrainThreadRun = true;
TerrainThread = CreateThread(NULL, NULL,(LPTHREAD_START_ROUTINE)TerrainThreadProc, 0, NULL, NULL);
while(!sharedContext)
Sleep(100);
if (wglMakeCurrent (window->hDC, window->hRC) == FALSE)
And in the thread:
if (!(window.hRCThread=wglCreateContext(window.hDCThread)))
{
//Error
}
while(wglShareLists(window.hRC, window.hRCThread) == 0)
{
DWORD err = GetLastError();
Sleep(5);
}
sharedContext = true;
int cnt = 0;
while(!wglMakeCurrent(window.hDCThread,window.hRCThread))
Sleep(5);
while(TerrainThreadRun)
{
//look for R
Second update: I tried using glMapBuffer instead of glBuferSubData, but the application behaves the same. Here is the code:
void *ptr = (void*)glMapBuffer(GL_ARRAY_BUFFER_ARB, GL_READ_WRITE_ARB);
if(ptr)
{
memcpy(ptr, g_pMesh->m_pVertices, g_pMesh->m_nVertexCount*3*sizeof(float));
glUnmapMapBuffer(GL_ARRAY_BUFFER_ARB);
}
Update three:
I was doing some things wrong, so I modified them, but the problem remains the same. Here is how I do everything now:
When the application loads, I create two windows, each with its own HWND. Based on them, I create two device contexts.
Then I share the lists between them:
wglShareLists(window.hRC, window.hRCThread);
This is done only once when I initialize.
After that I show the OGL window, which renders; I make the context active. Then I load the function pointers and create the VBO.
After the main rendering OGL is done, I create the thread. When the thread is loaded, I make its device context active.
Then we do normal stuff.
So my question is: Do I need to update the function pointers for each device context? Could this be my problem?
As an update, if I run my test app in gDEBugger and I first press "R" and then pause, it doesn't display correctly. I take a look at the memory (Textures, Buffers and Image Viewers) and GLContext1(I think the main rendering thread) device context has the OLD data. While GLContext2 (Shared-GL1) (I think the thread context) has the correct data.
The odd part, if I look back at GLContext1, with the program still in pause mode, now it displays the new data, like it "refreshed" it somehow. And then if I press play, it starts drawing correctly.
I found the solution, I need to call glFinish() in the worker thread after calling glUnmapBuffer. This will solve the problem and everything will render just fine.