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).
Related
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.
I'm editing shaders for Minecraft pe on my phone via ssh using a KDE terminal on my computer.
Syntax highlighting works good, but it does not show even simplest errors.
For example in this code below I have at list two errors, mostly lexical
vec4 no`rm`alColor;
void main(){
nomralColor = vec3(1.0,1.0,1.0,1.0);//vec3 != vec4
gl_FragColor = nomralColor;//normalColorl != nomralColor
}
Is there any possible way to check glsl code for simplest (at list lexical) errors using one of available command line code editors (nano/vim/micro)?
I suggest making a little tool you can use to check. The following code just prints out the error in the console window. You could be coding in C++ or Java for Android, I'll give you my C++ example because all the OpenGL calls are the same in Java too.
It's pretty short really, you just use glCreateShader() and glCompileShader() to try to compile it, followed by glGetShaderInfoLog() to give you the error message(s).
//tell openGL to do all the work for us
bool compileShader(GLuint shaderID, std::string shaderCode) {
// Compile Shader
glShaderSource(shaderID, 1, (const char* const*)shaderCode.c_str(), NULL);
glCompileShader(shaderID);
// Check Shader
GLint Result = GL_FALSE;
int InfoLogLength;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
// Do we have an error message?
if (InfoLogLength > 0){
std::vector<char> shaderErrorMessage(InfoLogLength + 1);
// Get the message text
glGetShaderInfoLog(shaderID, InfoLogLength, NULL, &shaderErrorMessage[0]);
#ifdef DBG_SHADER
printf("Compilation error:\n%s", &shaderErrorMessage[0]);
#endif
return false;
}
return true;
}
and the usage of that function is, given a string of code called FragmentShaderCode
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
bool succeeded = compileShader(FragmentShaderID, FragmentShaderCode);
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.
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
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.