In my fragment shader I have the following function
void InitLookUpTables()
{
return;
}
Which I call directly in my main function. So when I delete this function call I can't compile this shader anymore, I receive the following error:
0(120) : error C5041: cannot locate suitable resource to bind variable
"#TMP118". Possibly large array.
Indeed, I have an array of 512 ints in this shader, so it sounds reasonable. I just wonder why is this empty function makes things work.
Related
I have a problem using the "setUniformArray" method. I want to pass a std::vector to the shader in this way:
void OutputShader::setUniform(const std::string &name, const std::vector<float>& arr) {
outputShader.setUniformArray(name, arr.data(), arr.size());
}
In fragment shader I wrote like this:
uniform float "vector_name"[];
As a result I am getting the error:
Uniform "vector_name" not found in shader
Can you tell me the cause of the error and how to fix it please
My problem is solved
The fact is that this array was not used anywhere else and it seems that it was "thrown out" during compilation, so when I was trying to set a value to it, an error was generated
e.g. when I do
glBindBuffer(GL_ARRAY_BUFFER, _id);
glNamedBufferData(_id, size, data, static_cast<GLenum>(usage));
then program works as expected. But if I delete that first line, my program crashes and prints:
ERROR 1282 in glNamedBufferData
Likewise, if I do
glBindVertexArray(_id);
GLuint attribIndex = 0;
GLuint offset = 0;
for(const GlslType type : layout) {
const auto& attrib = GLSL_TYPES.at(type);
glVertexArrayAttribFormat(_id, attribIndex, attrib.size, static_cast<GLenum>(attrib.type), GL_FALSE, offset);
glEnableVertexArrayAttrib(_id, attribIndex);
glVertexArrayAttribBinding(_id, attribIndex, 0);
offset += attrib.size_bytes();
}
It works fine, but if I delete the glBindVertexArray then it doesn't work and prints:
ERROR 1282 in glVertexArrayAttribFormat
ERROR 1282 in glEnableVertexArrayAttrib
ERROR 1282 in glVertexArrayAttribBinding
I figured that by "naming" the VBO or VAO when calling those functions then I wouldn't have to bind it beforehand. But if I have to bind regardless, what's the benefit of these functions that require the extra name argument?
The glGen* functions create a integer name representing an object, but they don't create the object state itself (well, most of them don't). It is only when you bind those objects do they gain their state, and only after they have state can any function be called which requires them to have state. In particular, the direct state access functions.
This is why ARB_direct_state_access also includes the glCreate* functions. These functions create an integer name and the state data for objects. Therefore, you don't have to bind anything to manipulate direct state access functions, so long as you properly created the object beforehand.
The code below wasn't working for 2 days and after I've fiddled around with it, created new functions, rewrote them, deleted them and now, strangely, it works! I'm afraid there's a fundamental c++ error and my noob brain can't see it.
void Shader::SetMat4(const char* key, const glm::mat4 &value) {
uint loc = glGetUniformLocation(id, key); // id is the program id stored as member var
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(value));
}
If I set the uniform directly in the calling function instead of doing shader->SetMat4 it was working, but this just refused to work.
I suspect it has something to do with the way I'm passing a mat4 reference and in the way value_ptr returns const *mat4::value_type, but I don't see it. And now I'm afraid there's something in my code that will bite me a year from now :|.
Recently I got a segfault when reading atomic counters via glMapBuffer. Here is the code:
GLuint atomicCounter[2];
inline void getAtomicCounters()
{
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, ATOMIC_COUNTER_INDEX, acBuffer);
CHECK_FOR_GL_ERRORS();
static GLuint* data = (GLuint*)glMapBuffer(GL_ATOMIC_COUNTER_BUFFER, GL_READ_ONLY);
CHECK_FOR_GL_ERRORS();
atomicCounter[0] = data[0];
atomicCounter[1] = data[1];
glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
CHECK_FOR_GL_ERRORS();
}
The problem seems to be that data is a static pointer. When I remove the static keyword, everything works perfectly. I know that I don't need a static pointer, it was just a test and I'm quite surprised that it won't work with a static pointer. Does anybody know why a segfault occurs at "atomicCounter[0] = data[0];"?
This is not at all surprising.
Do you understand how a variable declared with the static qualifier in the body of a function works in C++? It will be initialized with that value the first time the function (getAtomicCounters (...)) runs, but each subsequent execution will skip-over the initialization:
static GLuint* data =
(GLuint*)glMapBuffer(GL_ATOMIC_COUNTER_BUFFER, GL_READ_ONLY);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//This is only evaluated the first time you call this function!
So every subsequent call is going to use the value of data you initialized the first time. The elephant in the room is that the value of data became invalid when you made this call: glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
You can fix this simply by assigning data the return value of glMapBuffer (...) on a separate line from the one where you declare the variable. Then it will always execute glMapBuffer (...) when you call this function.
However, to be completely honest, I can see no reason why you would need or even want static storage for your data pointer.
I have a very simple class that looks as follows:
class CHeader
{
public:
CHeader();
~CHeader();
void SetCommand( const unsigned char cmd );
void SetFlag( const unsigned char flag );
public:
unsigned char iHeader[32];
};
void CHeader::SetCommand( const unsigned char cmd )
{
iHeader[0] = cmd;
}
void CHeader::SetFlag( const unsigned char flag )
{
iHeader[1] = flag;
}
Then, I have a method which takes a pointer to CHeader as input and looks
as follows:
void updateHeader(CHeader *Hdr)
{
unsigned char cmd = 'A';
unsigned char flag = 'B';
Hdr->SetCommand(cmd);
Hdr->SetFlag(flag);
...
}
Basically, this method simply sets some array values to a certain value.
Afterwards, I create then a pointer to an object of class CHeader and pass it to
the updateHeader function:
CHeader* hdr = new CHeader();
updateHeader(hdr);
In doing this, the program crashes as soon as it executes the Hdr->SetCommand(cmd)
line. Anyone sees the problem, any input would be really appreciated
When you run into a crash, act like a crime investigator: investigate the crime scene.
what is the information you get from your environment (access violation? any debug messages? what does the memory at *Hdr look like? ...)
Is the passed-in Hdr pointer valid?
Then use logical deduction, e.g.:
the dereferencing of Hdr causes an access violation
=> passed in Hdr points to invalid memory
=> either memory wasn't valid to start with (wrong pointer passed in), or memory was invalidated (object was deleted before passing in the pointer, or someone painted over the memory)
...
It's probably SEGFAULTing. Check the pointers.
After
your adding some source code
your comment that the thing runs on another machine
the fact that you use the term 'flag' and 'cmd' and some very small datatypes
making me assume the target machine is quite limited in capacity, I suggest testing the result of the new CHeader for validity: if the system runs out of resources, the resulting pointer will not refer to valid memory.
There is nothing wrong with the code you've provided.
Are you sure the pointer you've created is the same same address once you enter the 'updateHeader' function? Just to be sure, after new() note the address, fill the memory, sizeof(CHeader), with something you know is unique like 0XDEAD, then trace into the updateHeader function, making sure everything is equal.
Other than that, I wonder if it is an alignment issues. I know you're using 8 bit values, but try changing your array to unsigned ints or longs and see if you get the same issue. What architecture are you running this on?
Your code looks fine. The only potential issue I can see is that you have declared a CHeader constructor and destructor in your class, but do not show the implementation of either. I guess you have just omitted to show these, else the linker should have complained (if I duplicate this project in VC++6 it comes up with an 'unresolved external' error for the constructor. It should also have shown the same error for the destructor if you had a... delete hdr; ...statement in your code).
But it is actually not necessary to have an implementation for every method declared in a class unless the methods are actually going to get called (any unimplemented methods are simply ignored by the compiler/linker if never called). Of course, in the case of an object one of the constructor(s) has to be called when the object is instantiated - which is the reason the compiler will create a default constructor for you if you omit to add any constructors to your class. But it will be a serious error for your compiler to compile/link the above code without the implementation of your declared constructor, so I will really be surprised if this is the reason for your problem.
But the symptoms you describe definitely sounds like the 'hdr' pointer you are passing to the updateHeader function is invalid. The reason being that the 1st time you are dereferencing this pointer after the updateHeader function call is in the... Hdr->SetCommand(cmd); ...call (which you say crashes).
I can only think of 2 possible scenarios for this invalid pointer:
a.) You have some problem with your heap and the allocation of memory with the 'new' operator failed on creation of the 'hdr' object. Maybe you have insufficient heap space. On some embedded environments you may also need to provide 'custom' versions of the 'new' and 'delete' operator. The easiest way to check this (and you should always do) is to check the validity of the pointer after the allocation:
CHeader* hdr = new CHeader();
if(hdr) {
updateHeader(hdr);
}
else
//handle or throw exception...
The normal behaviour when 'new' fails should actually be to throw an exception - so the following code will cater for that as well:
try{
CHeader* hdr = new CHeader();
} catch(...) {
//handle or throw specific exception i.e. AfxThrowMemoryException() for MFC
}
if(hdr) {
updateHeader(hdr);
}
else
//handle or throw exception...
}
b.) You are using some older (possibly 16 bit and/or embedded) environment, where you may need to use a FAR pointer (which includes the SEGMENT address) for objects created on the heap.
I suspect that you will need to provide more details of your environment plus compiler to get any useful feedback on this problem.