1

I'm having a bit of a problem with my code for compiling shaders, namely they both register as failed compiles and no log is received.

This is the shader compiling code:

/* Make the shader */

Uint size;
GLchar* file;

loadFileRaw(filePath, file, &size);

const char * pFile = file;
const GLint pSize = size;


newCashe.shader = glCreateShader(shaderType);
glShaderSource(newCashe.shader, 1, &pFile, &pSize); 
glCompileShader(newCashe.shader);

GLint shaderCompiled;

glGetShaderiv(newCashe.shader, GL_COMPILE_STATUS, &shaderCompiled);

if(shaderCompiled == GL_FALSE)
{
    ReportFiler->makeReport("ShaderCasher.cpp", "loadShader()", "Shader did not compile", "The shader " + filePath + " failed to compile, reporting the error - " + OpenGLServices::getShaderLog(newCashe.shader));

}

And these are the support functions:

bool loadFileRaw(string fileName, char* data, Uint* size)
{    
    if (fileName != "") 
    {
        FILE *file = fopen(fileName.c_str(), "rt");

        if (file != NULL) 
        {
            fseek(file, 0, SEEK_END);
            *size = ftell(file);
            rewind(file);

            if (*size > 0) 
            {
                data = (char*)malloc(sizeof(char) * (*size + 1));
                *size = fread(data, sizeof(char), *size, file);
                data[*size] = '\0';
            }

            fclose(file);
        }
    }

    return data;
}

string OpenGLServices::getShaderLog(GLuint obj)
{
    int infologLength = 0;

    int charsWritten  = 0;
    char *infoLog;

    glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infologLength);

    if (infologLength > 0)
    {
        infoLog = (char *)malloc(infologLength);
        glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);

        string log = infoLog;

        free(infoLog);

        return log;
    }

    return "<Blank Log>";
}

and the shaders I'm loading:

void main(void)
{
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

void main(void)
{
    gl_Position = ftransform();
}

In short I get

From: ShaderCasher.cpp, In: loadShader(), Subject: Shader did not compile
Message: The shader Data/Shaders/Standard/standard.vs failed to compile, reporting the error - <Blank Log>

for every shader I compile.

I've tried replacing the file reading with just a hard coded string but I get the same error so there must be something wrong with how I'm compiling them. I have run and compiled example programs with shaders, so I doubt my drivers are the issue, but in any case I'm on a Nvidia 8600m GT.

Can anyone help?

3
  • It's not an exact duplicate, but you might find this answer helpful: stackoverflow.com/questions/2795044/… Commented May 27, 2010 at 17:24
  • are you free() -ing your data anywhere after loadFileRaw()? Unless I'm missing something, I see a memory leak. Commented May 28, 2010 at 10:23
  • I was planning to cache or display the shader source code somewhere if the compiling fails, but I don't currently have a logger sophisticated enough to do that in a format which is easy to read. I was aware of needing to free the data though, but once that test compile fails you toss all other things aside to find the problem. Commented May 28, 2010 at 15:44

2 Answers 2

4

In loadFileRaw, you pass char *data by value. Then you assign to it:

data = (char*)malloc(sizeof(char) * (*size + 1));

so your call

loadFileRaw(filePath, file, &size);

does not change the value of file! To change file, pass it in by pointer:

loadFileRaw(filePath, &file, &size);

and then change your function to

bool loadFileRaw(string fileName, char** data, Uint* size) { ... }

and in it,

*data = (char*)malloc(sizeof(char) * (*size + 1));

etc. (for the remaining references to data).

That said, since you're using C++, look into using std::vector<char> or std::string for your memory management. To get you started,

{
   std::vector<char> data;
   data.resize(100); // now it has 100 entries, initialized to zero
   silly_C_function_that_takes_a_char_pointer_and_a_size(&data[0], 100); // OK
} // presto, memory freed

Also, you can look into using std::ifstream for reading files, instead of using FILE *.

Sign up to request clarification or add additional context in comments.

4 Comments

My original function used std::ifstream, but I copied the one shown off the internet once I had this problem. Urgh, now I'm getting bad access on glShaderSource
If I make the read function use std::string, won't it need to use chars for the ifstream functions anyway?
@Tomas, I don't follow your second question, but it looks like you're having some trouble with pointers, so why don't you put shaders on hold for a moment and carefully work some simpler examples with pointers (including, but not only, C-style strings) until you feel more comfortable.
I changed my function into one which used strings instead and everything working fine - thanks for the advice. What I was trying to say one comment up was that since fstream's functions all take pointers to chars to send data back, getting it in that form then converting it to a string, only to convert it back for opengl seemed a bit redundant. In any case I found a workaround in an article somewhere which used stringstream and reader->rdbuf() - it seems like a waste of time, but hey, it works. Cheers for the advice and all
1

Try with:

glShaderSource(newCashe.shader, 1, &pFile, NULL);

Which is the most commonly used call to load shader sources.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.