Sign in to follow this  
proanim

how to avoid macro loops

Recommended Posts

If found some source code that has this in it

 

 

 

#define FOR(q,n) for(int q=0;q<n;q++)
#define SFOR(q,s,e) for(int q=s;q<=e;q++)
#define RFOR(q,n) for(int q=n;q>=0;q--)
#define RSFOR(q,s,e) for(int q=s;q>=e;q--)
#define ESZ(elem) (int)elem.size()
 
 
and it is used as
 
const char** sProgram = new const char*[ESZ(sLines)];
FOR(i, ESZ(sLines))sProgram[i] = sLines[i].c_str();
 
How should i make these loops so i dont have to use these macros?
I tried this
 
 
const char** sProgram = new const char* [(int)sLines.size()];
 
int i = 0;
for(i; sLines.size(); i++)
sProgram[i] = sLines[i].c_str();
 
but the for loop gets vector out of bounds error when it hits last line in file (this is used in function that reads text file)

 

Share this post


Link to post
Share on other sites

In case you use GCC, you can compile with -save-temps to trivially figure out any macro abuse, no matter how convoluted it is. For every file foo.c you will find a file foo.ii generated, which contains the output of the preprocessor (i.e. with everything included, and all macros expanded). I've found this immensely helpful at times.

Share this post


Link to post
Share on other sites

I'm with Servant of the Lord on this. Are you really sure you need to do this?

 

Sometimes you have to question the quality of your sources. In this case, it's not only converting away from std::string to unsafe raw strings that is a code smell, but the use of macros in this situation also smells nasty. Macro usage like this can conceal or even introduce bugs, and detracts from readability, making it a confusing mess for no real reason other than somebody thought they could save some typing. If they took shortcuts there, the remainder of their code might be smelly, too.

 

What is it you are trying to accomplish in the larger scheme? Maybe we can help you figure out a less smelly method.

Share this post


Link to post
Share on other sites
Well it is 'simple' process - the function opens file for reading, reads through entire file with this

// get all lines from a file
vector<string> sLines;
char sLine[255];
while(fgets(sLine, 255, fp))sLines.push_back(sLine);
fclose(fp);

then it does this

const char** sProgram = new const char* [(int)sLines.size()];

int i = 0;
for(i; i < sLines.size(); i++)
sProgram[i] = sLines[i].c_str();

and processes entire file as needed and does

delete[] sProgram;

now when i look at this I see that I never free sLines vector is that needed? Edited by proanim

Share this post


Link to post
Share on other sites

Ok i made changes and now same stuff happens only difference is now i can't complete the entire process. There is no error or anything the funtion returns false

 

bool CShader::loadShader(string sFile, int a_iType)
{
	//FILE* fp = fopen(sFile.c_str(), "rt");
	//if(!fp)return false;

	// get all lines from a file
	vector<string> sLines;
	//char sLine[255];
	//while(fgets(sLine, 255, fp))sLines.push_back(sLine);
	//fclose(fp);

	ifstream infile(sFile.c_str());

	while(!infile.eof())
	{
		string s;
		getline(infile, s);
		sLines.push_back(s);
	}

	infile.close();

	//const char** sProgram = new const char*[ESZ(sLines)];
	//FOR(i, ESZ(sLines))sProgram[i] = sLines[i].c_str();
	
	//const char** sProgram = new const char* [(int)sLines.size()];
	vector<const char *> sProgram;

	//for(int i; i < sLines.size(); i++)
	//	sProgram[i] = sLines[i].c_str();
	for(unsigned int i=0; i<sLines.size(); ++i)
		sProgram.push_back(sLines[i].c_str());

	uiShader = glCreateShader(a_iType);

	glShaderSource(uiShader, sLines.size(), &sProgram[0], NULL);
	glCompileShader(uiShader);

	//delete[] sProgram;

	int iCompilationStatus;
	glGetShaderiv(uiShader, GL_COMPILE_STATUS, &iCompilationStatus);

	if(iCompilationStatus == GL_FALSE)return false;
	iType = a_iType;
	bLoaded = true;

	return 1;
}

 

What can cause glGetShaderiv(uiShader, GL_COMPILE_STATUS, &iCompilationStatus); to fail ? Shader files that i use with this are basic color shaders and they work with orginal function but now they fail to compile, I am not sure why exactly.

Share this post


Link to post
Share on other sites

Why don’t you show the code you are using to get said results?

 

 

Also, your way of loading the shader is dreadful (why not just load the file into memory, add a 0 at the end, and pass that directly to ::glShaderSource() instead of wasting time creating an array of char *’s?), but I don’t see any bugs in it.

So why not save a reply and also post the shader code since that seems more likely to be the source of the error?

 

 

L. Spiro

Edited by L. Spiro

Share this post


Link to post
Share on other sites
So why not save a reply and also post the shader code since that seems more likely to be the source of the error?

Shaders are working in first version of the function

 

 

 

vertex shader:

#version 330

layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec3 inColor;

smooth out vec3 theColor;

void main()
{
	gl_Position = vec4(inPosition, 1.0);
	theColor = inColor;
}

 

 

fragment shader

 

#version 330

smooth in vec3 theColor;
out vec4 outputColor;

void main()
{
	outputColor = vec4(theColor, 1.0);
}

 

 

these are loaded with

// Load shaders and create shader program
shVertex.loadShader("data/shaders/color.vert", GL_VERTEX_SHADER);
shFragment.loadShader("data/shaders/color.frag", GL_FRAGMENT_SHADER);

Share this post


Link to post
Share on other sites

What L. Spiro is saying, in case it's not obvious, is that you're not showing how you're getting this error log back...  Your earlier post shows some good info on how you're compiling your shader, but it doesn't show how you're obtaining that strange error log.

 

It's kinda like trying to diagnose a patient, if you're a doctor, and he says "I have symptoms" but doesn't say what those symptoms are :)

Edited by Cornstalks

Share this post


Link to post
Share on other sites
glShaderSource(uiShader, sLines.size(), &sProgram[0], NULL);
glCompileShader(uiShader);

int infologLength;
int maxLength;
char* infoLog;

glGetShaderiv(uiShader,GL_INFO_LOG_LENGTH, &maxLength);
glGetShaderInfoLog(uiShader, maxLength, &infologLength, infoLog);

ofstream outfile;
outfile.open ("log.txt");
outfile << &infoLog << endl;
outfile.close();

Share this post


Link to post
Share on other sites

Santa01 showed above how to get the log from the shader or program object. Your code has two major problems though:

  1. glGetShaderInfoLog expect you to allocate the buffer so that it can write the log to it. You're not allocating anything and so the function is writing to wherever the pointer happens to point. In this case, it's trashing the stack big time.
  2. infoLog is char *, and so infoLog itself is the string containing the log, not &intoLog. Output as a string is only overloaded for char * (with combinations of cv-qualifiers), but &infoLog is a char **  which just prints the address of the infoLog variable.

Share this post


Link to post
Share on other sites

finally, so the errors are this

 

Fragment shader failed to compile with the following errors:
ERROR: 2:1: error(#307) Profile "smooth" is not supported
ERROR: 2:1: error(#76) Syntax error: unexpected tokens following #version
ERROR: error(#273) 2 compilation errors.  No code generated

 

any ideas?

Share this post


Link to post
Share on other sites
My guess is the dreadful mess of code you are using to load the shader text.
 
Specifically:
getline(infile, s);
should be:
getline(infile, s);
s.append( endl );
I had assumed originally that ::glShaderSource() would treat each line you passed to it as…a line.
But closer reading reveals that all it does is put all the lines back together just as you pass them to the function, which means if you don’t have line endings then it will be passed to the compiler as a shader written entirely on one line. The reason it sees “330” and “smooth” as separate identifiers is because there is a hidden \r between them that was not discarded by getline(), but inside the shader/compiler that does not constitute a new line, so it basically sees this: “#version 330 smooth in vec3 […]”.

This is exactly why I call your loading code a dreadful mess.
You load the whole file, expand it into an array of lines (which removes the \n line-ending), make another array of pointers into that, then pass that whole thing to OpenGL, and all OpenGL does internally is make it all back into one single long line of text, which is exactly what you had (minus new lines) when you loaded it directly from the file in the first place before you did all that mess of array creation and line-by-line parsing.

You basically spent a lot of time writing a complex loader whose only purpose is to remove new-lines and create bugs.
Why not do as I suggested and just load the file directly to memory, append a 0, and pass it as-is with no further parsing to OpenGL?
santa01 showed you how to do it.  It is 10 times less complex, 100 times faster, and 10 times less error-prone.
 
 
L. Spiro Edited by L. Spiro

Share this post


Link to post
Share on other sites

It works with s.append("\n"); no problem.

 

Also when I try to read the file as santa01 suggested there is something wierd happening. When function gets vertex shader it reads through it and exits just before

 

    theColor = inColor;
}

 

and when it reads through fragment shader it read the file entirely and adds some garbage characters at the end (when debugging).

 

I never used this approach so I might be missing something.

Share this post


Link to post
Share on other sites

Are you phil67rpg?

If you made changes to your code and you have new errors, post the new code.  It helps us not to take shots in the dark when trying to guess what your problem could be.

 

Anyway it sounds as though you either forgot to add the 0 or you added the 0 but at a fixed position.

I surely hope you did not forget the 0 because I mentioned it twice and it was included in the santa01’s code.

 

If you are inserting it at a fixed or miscalculated position it would explain why one shader is too short and the other is too long.

 

 

Again, nothing but conjecture until we see some code.

 

 

L. Spiro

Share this post


Link to post
Share on other sites

This is the code I used 

 

ifstream file(sFile.c_str(), ios::binary);

	file.seekg(0, ios::end);
    int sourceLength = file.tellg(); // warning C4244: 'initializing' : conversion from 'std::streamoff' to 'int', possible loss of data
    GLchar* shaderSource = new GLchar[sourceLength + 1];
 
    file.seekg(0, ios::beg);
    file.read(shaderSource, sourceLength);
    shaderSource[sourceLength] = 0;
 
	file.close();

    uiShader = glCreateShader(a_iType);
    glShaderSource(uiShader, 1, (const GLchar**)&shaderSource, NULL);
    glCompileShader(uiShader);
 
    delete[] shaderSource;

    GLint compileStatus;
    glGetShaderiv(uiShader, GL_COMPILE_STATUS, &compileStatus);

    if (compileStatus == GL_FALSE)
	{
        GLint infoLogLength;
        glGetShaderiv(uiShader, GL_INFO_LOG_LENGTH, &infoLogLength);
        
        GLchar* infoLog = new GLchar[infoLogLength + 1];
        glGetShaderInfoLog(uiShader, infoLogLength, NULL, infoLog);
        
		ofstream outfile;
		outfile.open ("log.txt");
		outfile << infoLog << endl;
		outfile.close();

        delete[] infoLog;
    }

 

it is almost exactly the same as santa01's.

 

You say that santa01's code did include 0 (where is it?)

Share this post


Link to post
Share on other sites
it is almost exactly the same as santa01's.

 

You say that santa01's code did include 0 (where is it?)

 

Its on line:

shaderSource[sourceLength] = 0;

which does present in your sources...

 

you can always print shaderSource to stdout to see if there is any extra crap in the buffer. its also useful to look through the shaderSource contents in your IDE under debug, IDEs do usually print special character with their symbolic representation like \r\n etc. for instance if you develop under MacOS X you gonna have \r whereas shader compiler could expect \n instead, hence compilation errors.

 

and it definitely won't harm to examine shader source file in hex editor to check its real contents :)

Share this post


Link to post
Share on other sites

When i print the content of shaderSource to file with

 

ofstream outfile;
outfile.open ("log.txt", fstream::out | fstream::app);
outfile << shaderSource << endl;
outfile << endl;
outfile.close();

 

I get normal contents of vertex and fragment shader - no extra symbols or anything.

 

But when I use debugger I see this

 

 

63944468.jpg
 
and this
 

36815480.jpg
 
any ideas?

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this