Struggling to understand why I'm getting an error

I’m getting an invalid operation error at this call (a few lines after creating the buffer)

	GLCALL
    	(
    		NULL
    		, glVertexAttribPointer
    		(
    			0
    			, sizeof(GFX_FPOINT) / sizeof(float)
    			, GL_FLOAT
    			, GL_FALSE
    			, sizeof(GFX_FPOINT)
    			, NULL
    		)
    	);

Does anyone have any ideas?

For full context here’s the function it’s called in:

void init_vertex_fpoints_buffer( GFX_OBJECT *o )
{
	GFX_FPOINTS *f = &(o->fpoints);
	GLCALL( NULL, glGenBuffers( 1, &(f->id) ) );
	GLCALL( NULL, glBindBuffer( f->type, f->id ) );
	GLCALL( NULL, glBufferData( f->type, f->size, f->data, f->hint ) );
#if 1
	GLCALL
	(
		NULL
		, glVertexAttribPointer
		(
			0
			, sizeof(GFX_FPOINT) / sizeof(float)
			, GL_FLOAT
			, GL_FALSE
			, sizeof(GFX_FPOINT)
			, NULL
		)
	);
#endif
}

I’ll take the lack of replies as an indication there’s not enough info, what else should I put in?

I’ve also started having an issue with my shaders, tried to condense some code to functions so that it would be less error prone, instead I ended up with errors, I also changed some code in the shaders themselves but I REALLY doubt that that’s it.

Output:

make run
INCS=-I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/harfbuzz -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include
LIBS=-lfreetype  -l glfw -l GL -l GLEW
CFLAGS=-g
cc INCS CFLAGS -o main.c.o -c main.c LIBS
make: Circular GNUmakefile.o <- GNUmakefile dependency dropped.
cc INCS CFLAGS main.c.o angle.c.o LIBS
./a.out
[OPENGL SHADER ERROR] 8192 bytes:
res/builder.glsl:0:
Code:
#version 330 core
in vec3 v3InPoint;
void main()
{
	gl_Position = vec4(v3InPoint, 1.0);
}
make: *** [GNUmakefile:26: run] Error 1
Compilation failed.

The code that loads it into the GFX card:

void debug_shader( GFX_CRAFTER *program, GFX_CRAFTER *crafter )
{
	char *log;
	unsigned int size = program->size;
	
	glGetShaderiv( crafter->id, GL_INFO_LOG_LENGTH, &size );
	
	size = (size >= program->size) ? size + 1 : program->size;
	size += (BUFSIZ - (size % BUFSIZ));
	log = realloc( program->code, size );
	
	if ( !log )
	{
		log = program->code;
		size = program->size;
	}
	
	program->code = log;
	program->size = size;
	
	memset( log, 0, size );
	glGetShaderInfoLog( crafter->id, size, NULL, log );
	
	fprintf
	(
		stderr
		, "[OPENGL SHADER ERROR] %u bytes:\n%s:%u:\n%s\nCode:\n%s\n"
		, size
		, crafter->path
		, crafter->line
		, log
		, crafter->code
	);
}

int init_crafters( GFX_CRAFTER *program, GFX_BUFFER *crafters )
{
	GFX_CRAFTER *_crafters = crafters->data;
	load_crafter( &_crafters[0], "res/builder.glsl", GL_VERTEX_SHADER );
	load_crafter( &_crafters[1], "res/painter.glsl", GL_FRAGMENT_SHADER );
	
	for ( int i = 0; i < crafters->used; ++i )
	{
		GFX_CRAFTER *crafter = _crafters + i;
		unsigned int leng;
		char const * const code[] = { crafter->code, NULL };
		
		crafter->id = glCreateShader( crafter->type );
		
		glShaderSource( crafter->id, 1, code, NULL );
		glGetShaderiv( crafter->id, GL_SHADER_SOURCE_LENGTH, &leng );
		
		if ( leng )
		{
			glCompileShader( crafter->id );
			glGetShaderiv( crafter->id, GL_COMPILE_STATUS, &(crafter->built) );
			
			if( crafter->built )
				continue;
		}
		else
		{
			fprintf
			(
				stderr
				, "[OPENGL SHADER ERROR]\n%s:%u"
				, crafter->path
				, crafter->line
			);
		}
		
		debug_shader( program, crafter );
		
		while ( i )
		{
			--i;
			crafter = crafter + i;
			glDeleteShader( crafter->id );
			crafter->id = 0;
			crafter->built = 0;
		}
		
		return -1;
	}
	
	return 0;
}

Vertex Shader Code:

#version 330 core
in vec3 v3InPoint;

void main()
{
	gl_Position = vec4(v3InPoint, 1.0);
}

Fragment Shader Code:

#version 330 core
layout (location = 0) out vec4 v4OutColour;

uniform vec3 uInColour;

void main()
{
	v4OutColour = vec4( uInColour, 1.0 );
}

Edit: Never mind about the shader error, turned out I forgot to fill the crafter->type field at the end of load_crafter(), fixing that resolved the shader errors… for now at least, being a newb to shaders I’m bound to screw up later, especially if I get round to trying out an idea I had this morning of utilising them for compiling many files at once from c to asm then to objects then write it all back to disk, would make rebuilding entire projects many times faster

The main thing that’s blocking at least me from being able to even begin to assist is that you have all these custom classes, structures and macros, but you’re not telling us what they’re doing. The quote I have here is a great example : there’s absolutely no way anybody on this board could have solved that for you.

Who’s to say that your original problem doesn’t have a similar cause?

On the whole though, this seems like the kind of thing you should be able to single-step in a debugger. Break on each line of code, examine your parameters to your GL calls, determine which code is bad, and fix it.

Well for the custom “classes” (which are actually structs, I don’t like using c++), I thought you would’ve inferred the purpose from the parameter usage when I call opengl functions, I went with the name GFX_CRAFTER instead of GFX_SHADER because shader is a poor name to begin with, who though calling something that builds vertex points a shader (which implies giving a shade of colour) was a good idea? For the fragment shader that was fine but for the vertex “shader” that is just a poor name. For the rest of the thread I’ll just call them crafters which is less confuing.

Anyways while I was continuing to watch some OpenGL vids from https://www.youtube.com/playlist?list=PLlrATfBNZ98foTJPJ_Ev03o2oq3-GGOS2 I finally saw the problem, turned out I was programming in core mode and opengl was trying (very poorly I might add) to tell me that there was no vertex arrays created which meant that 0 at the start was invalid. That’s seemingly fixed now but in the process of adding uniforms the crafters failed to compile, tell me if you can make sense of this:

make rebuild run --no-print-directory
cd ../ && make  rebuild run
INCS=-I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/harfbuzz -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include
LIBS=-lfreetype  -l glfw -l GL -l GLEW
CFLAGS=-g
rm -f *.out *.o
cc INCS CFLAGS -o main.c.o -c main.c LIBS
make[1]: Circular GNUmakefile.o <- GNUmakefile dependency dropped.
cc INCS CFLAGS -o angle.c.o -c angle.c LIBS
cc INCS CFLAGS main.c.o angle.c.o LIBS
./a.out
main.c:510: [OPENGL SHADER ERROR] 0x00000000 (0), source expects 174 characters
res/builder.glsl:0
main.c:432: [OPENGL SHADER ERROR] 8192 bytes:
res/builder.glsl:0:
0:4(1): error: duplicate storage qualifier
0:4(1): error: invalid input layout qualifier used
0:5(1): error: duplicate storage qualifier
0:5(1): error: invalid input layout qualifier used
0:6(1): error: duplicate storage qualifier
0:6(1): error: invalid input layout qualifier used
Code:
#version 330 core
in vec3 v3InPoint;
uniform in   int dInUserA;
uniform in float fInUserX;
uniform in float fInUserY;
void main()
{
	gl_Position = vec4(v3InPoint, 1.0);
}
cd ../ && make  rebuild run
INCS=-I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/harfbuzz -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include
LIBS=-lfreetype  -l glfw -l GL -l GLEW
CFLAGS=-g
rm -f *.out *.o
make[1]: Circular GNUmakefile.o <- GNUmakefile dependency dropped.
cc INCS CFLAGS -o main.c.o -c main.c LIBS
cc INCS CFLAGS -o angle.c.o -c angle.c LIBS
cc INCS CFLAGS main.c.o angle.c.o LIBS
./a.out
main.c:510: [OPENGL SHADER ERROR] 0x00000000 (0), source expects 174 characters
res/builder.glsl:0
main.c:432: [OPENGL SHADER ERROR] 8192 bytes:
res/builder.glsl:0:
0:4(1): error: duplicate storage qualifier
0:4(1): error: invalid input layout qualifier used
0:5(1): error: duplicate storage qualifier
0:5(1): error: invalid input layout qualifier used
0:6(1): error: duplicate storage qualifier
0:6(1): error: invalid input layout qualifier used
Code:
#version 330 core
in vec3 v3InPoint;
uniform in   int dInUserA;
uniform in float fInUserX;
uniform in float fInUserY;
void main()
{
	gl_Position = vec4(v3InPoint, 1.0);
}
Compilation finished successfully.

builder.glsl:

#version 330 core
in vec3 v3InPoint;

uniform in   int dInUserA;
uniform in float fInUserX;
uniform in float fInUserY;

void main()
{
	gl_Position = vec4(v3InPoint, 1.0);
}

painter.glsl:

#version 330 core
out vec4 v4OutColour;

in vec3 v3InColour;

uniform in   int dInUserA;
uniform in float fInUserX;
uniform in float fInUserY;

void main()
{
	v4OutColour = vec4( 0, 1.0, 1.0, 1.0 );
}

I was planning on passing the user angle & positions into both to see if I could tranlsate some code to the crafters so that a speed comparison could be done with raytracing (once I get round to actually adding the code that checks if objects are in boundaries of sight) but then this error happened.

uniform in” is invalid. Uniforms use “uniform”, attributes use “in”.

1 Like

That doesn’t tell us anything about their values, though. If the code which actually assigns the values is too removed from the OpenGL calls for anyone to comprehend, you’d be better off posting an apitrace log.

Well, if you’re using per-vertex lighting (like the fixed-function pipeline), the vertex shader is responsible for calculating the vertex colour from the lighting and material data and the vertex normal.

Hmm, I still find that a confusing naming scheme, I like my naming better, builder for the vertex crafter (implies main purpose is to build the vertex, adding lighting or colour can be considered a “while it’s at it” task), and painter for the fragment crafter (implies it’s only purpose is to give colour). The name crafter works for the program too so the same function could’ve been used for the creation part which makes doing it as the last item in a loop simple.

Anyways I tried that apitrace thing (there was a package for it so I just installed it from there), after fixing that uniform/in thing (which I might add is confusing, hoping the vid I’m watching on GLSL will explain that) and running that apitrace I got this:

make rebuild apitrace --no-print-directory
make -f main.mak rebuild
INCS=-I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/harfbuzz -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include
LIBS=-lfreetype  -l glfw -l GL -l GLEW
CFLAGS=-g
rm -f *.out *.o
cc INCS CFLAGS -o main.c.o -c main.c LIBS
cc INCS CFLAGS -o angle.c.o -c angle.c LIBS
cc INCS CFLAGS main.c.o angle.c.o LIBS
make -f main.mak apitrace
INCS=-I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/harfbuzz -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include
LIBS=-lfreetype  -l glfw -l GL -l GLEW
CFLAGS=-g
cc -g -D_DEBUG INCS CFLAGS -o main.cd.o -c main.c LIBS
cc -g -D_DEBUG INCS CFLAGS -o angle.cd.o -c angle.c LIBS
cc -g INCS CFLAGS -o d.out main.cd.o angle.cd.o LIBS
apitrace trace --api gl ./d.out
apitrace: loaded into /usr/bin/apitrace
apitrace: unloaded from /usr/bin/apitrace
apitrace: loaded into ~/d.out
apitrace: redirecting dlopen("libGL.so.1", 0x1) from /usr/lib/libglfw.so.3
apitrace: tracing to ~/d.out.trace
apitrace: attempting to read configuration file: /home/zxuiji/.config/apitrace/gltrace.conf
apitrace: warning: unknown function "glMultiDrawArraysIndirectCount"
apitrace: warning: unknown function "glMultiDrawElementsIndirectCount"
apitrace: warning: unknown function "glSpecializeShader"
apitrace: warning: unknown function "glNamedRenderbufferStorageMultisampleAdvancedAMD"
apitrace: warning: unknown function "glRenderbufferStorageMultisampleAdvancedAMD"
apitrace: warning: unknown function "glSpecializeShaderARB"
apitrace: warning: unknown function "glPolygonOffsetClamp"
apitrace: warning: unknown function "glEGLImageTargetTexStorageEXT"
apitrace: warning: unknown function "glEGLImageTargetTextureStorageEXT"
apitrace: warning: unknown function "glBufferStorageMemEXT"
apitrace: warning: unknown function "glCreateMemoryObjectsEXT"
apitrace: warning: unknown function "glDeleteMemoryObjectsEXT"
apitrace: warning: unknown function "glGetMemoryObjectParameterivEXT"
apitrace: warning: unknown function "glGetUnsignedBytei_vEXT"
apitrace: warning: unknown function "glGetUnsignedBytevEXT"
apitrace: warning: unknown function "glIsMemoryObjectEXT"
apitrace: warning: unknown function "glMemoryObjectParameterivEXT"
apitrace: warning: unknown function "glNamedBufferStorageMemEXT"
apitrace: warning: unknown function "glTexStorageMem1DEXT"
apitrace: warning: unknown function "glTexStorageMem2DEXT"
apitrace: warning: unknown function "glTexStorageMem2DMultisampleEXT"
apitrace: warning: unknown function "glTexStorageMem3DEXT"
apitrace: warning: unknown function "glTexStorageMem3DMultisampleEXT"
apitrace: warning: unknown function "glTextureStorageMem1DEXT"
apitrace: warning: unknown function "glTextureStorageMem2DEXT"
apitrace: warning: unknown function "glTextureStorageMem2DMultisampleEXT"
apitrace: warning: unknown function "glTextureStorageMem3DEXT"
apitrace: warning: unknown function "glTextureStorageMem3DMultisampleEXT"
apitrace: warning: unknown function "glImportMemoryFdEXT"
apitrace: warning: unknown function "glDeleteSemaphoresEXT"
apitrace: warning: unknown function "glGenSemaphoresEXT"
apitrace: warning: unknown function "glGetSemaphoreParameterui64vEXT"
apitrace: warning: unknown function "glIsSemaphoreEXT"
apitrace: warning: unknown function "glSemaphoreParameterui64vEXT"
apitrace: warning: unknown function "glSignalSemaphoreEXT"
apitrace: warning: unknown function "glWaitSemaphoreEXT"
apitrace: warning: unknown function "glImportSemaphoreFdEXT"
apitrace: warning: unknown function "glWindowRectanglesEXT"
apitrace: warning: unknown function "glMaxShaderCompilerThreadsKHR"
apitrace: warning: unknown function "glFramebufferParameteriMESA"
apitrace: warning: unknown function "glGetFramebufferParameterivMESA"
apitrace: warning: unknown function "glAlphaToCoverageDitherControlNV"
apitrace: warning: unknown function "glEGLImageTargetRenderbufferStorageOES"
apitrace: warning: unknown function "glEGLImageTargetTexture2DOES"
apitrace: unloaded from ~/d.out
Compilation finished successfully.

Make any sense to you?

If you do that, not only are you ignoring 25+ years of history, you will make your post incomprehensible to everyone who isn’t you. That isn’t helpful for the ability of anyone to help you solve your problem.

“Shader” is the term for a user-defined program used in a graphical context that executes within a rendering pipeline or for rendering purposes. Whether you think the terminology fits, that’s what it is, and its best to make your peace with it than trying to yell into a hurricane.

To expand on this, GLSL has “storage qualifiers” for global variables. These qualifiers define where the variable’s data comes from. C/C++ have storage qualifiers too, but not as many of them. The old qualifier register and the still active qualifier static say something about how the variable gets its storage.

uniform and in are both storage qualifiers, representing that the variable’s data is provided to the shader by OpenGL code and will not change within a draw command and that the variable’s data comes from a prior shader or pipeline stage, respectively. However, a variable can only have one storage qualifier: it can’t both come from OpenGL code and a prior pipeline stage.

So the compiler is complaining that your code is incoherent.

Sometimes you have to ignore history to improve things but putting that aside for now should I assume uniforms are global scope while ins are local scope then?

What do you mean by “scope”?

The term “scope” is usually meant to define the domain within a codebase from which typing the name of a variable will result in accessing that variable. Variables declared within a function are local to that function, and using the name of local variables from outside of the function will not access that function’s local variables.

The scope of a variable is defined by where it is declared. A variable defined within a function is local to the function (or block scope) in which it is declared. A variable declared outside of any function has global scope and can be named from anywhere within the code (unless the name conflicts with a locally-scoped variable accessible from that point in the code).

Scope has nothing to do with storage qualifiers. Scope defines who can access it; storage qualifiers define what you’re accessing.

Shader uniforms and shader stage inputs/outputs are always global variables. Therefore, their scope is always global.

Still not understanding the difference then, btw what I meant by scope was all GPU processors (what I belived uniform applied to) and individual processors (what I assumed ins applied to)

I don’t really know how to explain it any better. Scope is about what code gets to use the name and from where, not about what data is stored in it. Storage classes are about where the data comes from.

The word you’re looking for is “invocations”, not “processors”. A processor is a physical piece of hardware, and a GPU has a finite number of them. An “invocation” is an executing program, and a GPU can execute infinitely many of them.

Just not all at once. This is the difference between a CPU core and a thread; you have have as many threads as you like (OS and memory limitations aside), but you can only simultaneously execute the number of cores you have.

I thought the GPU just gave each instance of a program a whole processor since it has at least 100 of them, I thought the whole idea of a GPU was to do what a CPU can but at a larger scale (although by the looks of it the AMD Epyc may make that a thing of the past anyways sooner or later)

Edit: Forgot to mention but isn’t that source storage thing just a looser version of scope? That’s what I thought uniform and in meant, one stored in GDDR and the other stored on the processor.

Now you’re talking about how an instance executes. That’s a completely different conversation from what an instance actually is. And it varies from hardware to hardware.

But GPU resources are not infinite. They can only execute so many things at once. So if a rendering operation calls for more resources than can be executed at one time (which is most of the time), then some instances will have to wait until computational resources are available.

But that doesn’t change what an instance is.

No. Scope is about names and who can access them. Scope is not a thing that exists in the hardware. It’s part of the abstract model of the shading language. The hardware itself, the machine code being executed, has no idea what “scope” is.

It’s important for you to learn the right terminology. These words have very specific meanings in very specific contexts. And if you misuse them, you cannot effectively communicate with people.

How is it wrong? all instances of a program can access uniforms but only one instance can access the position colour data that was put into it, from my understanding ins are basically arguments/parameters provided to an instance while uniforms are something like a file just usually super tiny

Because it isn’t correct. I am not inventing terminology to be argumentative. I’m basically summarizing the OpenGL Shading Language specification which defines these terms:

The scope of a variable is determined by where it is declared. If it is declared outside all function definitions, it has global scope, which starts from where it is declared and persists to the end of the shader it is declared in. If it is declared in a while test or a for statement, then it is scoped to the end of the following sub-statement. If it is declared in an if or else statement, it is scoped to the end of that statement. (See “Selection” and “Iteration” for the location of statements and sub-statements.) Otherwise, if it is declared as a statement within a compound statement, it is scoped to the end of that compound statement. If it is declared as a parameter in a function definition, it is scoped until the end of that function definition. A function’s parameter declarations and body together form a single scope nested in the global scope. The if statement’s expression does not allow new variables to be declared, hence does not form a new scope.

I am not making these terms up. I am not using them arbitrarily or however I want. The document that defines what the OpenGL Shading language actually is defines these concepts as I have outlined them.

You don’t have to like these terms. But if you want to effectively communicate with other people, you have to use these terms in the agreed-upon fashion. And when talking about a construct like GLSL that has an actual document defining what language is, you should defer to the standard definitions for these terms since everyone else does.

You could also think of it as all instances of a program getting the same copy of uniform values but different in values.

But either way, this has nothing to do with “scope” as the language defines it. These are storage classes: they define how the variable gets its data. Scope defines who can access the variable.

Thought I understood with this statement then after thinking about it more I realised I still don’t understand, where do they source from?

It depends on the storage class. Indeed, that’s what the storage class is for: defining how the variable gets its data.

uniform variables get their data from values set in the program object. in variables get their data from values provided by prior stages in the pipeline.

In C/C++, when you declare a function-local variable, each instance of that function has a separate variable. When you declare a function-local variable with the static storage qualifier, every instance of that function is accessing the same variable.

That’s the kind of difference we’re talking about. Storage qualifiers specify where the variable lives. In C and C++, you can think of a function instance getting a block of memory to itself and also having a block of memory that all instances of that function can access. Non-static variables live in the first block, while static variables live in the second.

This is not meant to be a 1:1 analogy between C and GLSL. I only intend for it to describe the kind of thing that a storage qualifier represents: where the variable lives in memory. A shader instance could be said to have different pools of memory (we don’t care about how this is implemented), and each storage qualifier represents a different pool of memory. Some pools are shared between instances of the same program, and some are specific to an instance.

Exactly how that works depends on a lot of things, but again, this is a high-level overview of the kind of distinction we’re talking about.

1 Like

Okay that’s somewhat easier to understand, so would I be correct in thinking of the uniform something like a static class member, in being something like a instance based class member and out being something like an instance based class member holding a pointer to mapped data from memory?