gp4vp shader profile not available - Win7, Radeon HD4890

First of all, hello all! I must say, you have made one heck of a 3D engine here, of completely professional quality but open source and free! An absolute blessing for poor students like me :slight_smile:

Anyway, having seen the amazing screenshots on the blog, I have been trying to get hardware instancing working on my machine. Unfortunately, nothing seems to work (ranging from downloaded Python samples to self-made C++ code; always the same “INSTANCEID semantics not recognized”).
After a bit of hair-pulling, I decided that the mistake must be somewhere else than my code; I’ve downloaded the Panda3D sources and messed around a bit, and found an interesting thing in GLGraphicsStateGuardian::reset()… when the cgGLGetLatestProfile(…) functions are called, what they return is always arbvp1/arbfp1 (and a bit later on, “shader model 4” is also reported by some different function).
Now, I don’t know that much about shaders, but surely that isn’t right? The Radeon HD4890 isn’t the newest card around, but it’s pretty new and should support gp4vp, no?
I’ve searched around and came across this; Since am I also using Windows 7, I’d like to ask if this is some sort of unique issue? Or do these things also happen on other OSes?
I have updated my graphics card drivers yesterday, so I don’t think that’s the problem.

(oh, and please ignore the registration date :smiley: - I initially registered a LONG time ago, while I was still messing about with Python and encountering noobish mistakes; Ones that I fixed before managing to write up a post, hence leaving this account inactive for a LONG time, until recently, when I’ve finally returned to Panda3D, now with knowledge of C++).

Hey! Even though you’ve been around for a while, I’ll still welcome you to the forums. :slight_smile:

First of all, did you install the latest drivers for your video card?

Secondly, did you make sure that the “basic-shaders-only” Config.prc variable is set to #f or 0? Some developer added it a long time ago to restrict any shader to the arbvp1/arbfp1 profiles, as back then they appeared to be the only profiles that worked properly across graphics cards.

Thanks for the welcome.

I have indeed updated my drivers and set the “basic shaders only” variable - not only in the PRC file, but also through load_prc_file_data() to make absolutely sure that wasn’t it :smiley:

I’ve googled around a bit, and found that apparently, ATI cards only support the arbvp1/arbfp1 CG profiles, and no other ones (including the latest gen cards) - sounds incredibly stupid, but the fact that the cgGLGetLatestProfile() function itself seems to confirm it makes me think that really is the case.

Anyway, I’ve managed to translate the official hardware instancing example from the site into GLSL, where I can use gl_InstanceID without issues.
Unfortunately, I’ve ran into another big issue: I can’t seem to be able to pass float4 arrays into the shader. Individual float4’s work perfectly, but elements from an array seem to always give (0,0,0,0) when read [I’m using the standard PTA_LVecBase4f as a shader input].
Is there some special method required for GLSL? Or is this another ATI-related bug?

Hmm, if GLSL does work, then try forcing Panda to use the “glslv” and “glslf” profiles. Although not sure why cgGLGetLatestProfile would not return those.

This way, Cg will automatically translate the shaders into GLSL for you, so you can keep using Cg (and take advantage of the ability to pass arrays).

The CG code was automatically falling-back to glslv profiles (after trying gp4vp), but ‘unknown semantics “INSTANCEID”’ was the result, unfortunately.

Do you mean to say that GLSL doesn’t support uniform arrays? I was quite confident it did; Then again, my knowledge of GLSL currently comes from a few web tutorials and a single reference sheet, so yeah.
If it really doesn’t though, that would essentially mean that hardware instancing with Panda3D is not going to work on any ATI cards whatsoever… I’m seriously hoping I’ve made a noobish mistake somewhere!

Nah, it’s just not supported by Panda3D at the moment. A student from CMU added functionality to pass arrays at all, but only added it to the Cg side.

Ah, excellent! Since I’ve already got the Panda3D sources, I’ll look into adding my own implementation then (obviously, I’ll also put it up here once it’s relatively bugless, along with my translated GLSL instancing shader).

Also, thanks for all this help!

Ok, it seems to work now. I’ve attached the only file that I think I’ve changed (I’ve actually changed a few other files at first, then changed them right back while debugging / checking how Panda works, so I’m not completely sure this is the only one).
It’s fairly basic, but keeps things simple and doesn’t add any new strange data types or anything, so I’m hoping it’s usable. I’m fairly confident I didn’t break anything, but with such a huge codebase one can never be sure.
I’m also attaching my GLSL instancing shaders; I’ve translated them basically line-for-line from the official examples, and they should be useful enough for owners of ATI cards.

Now, for my project, I still need to implement rotation - the obvious solution is to create a rotation matrix based on a vec3 input array (of h,p,r angles), then operate it onto the position vector. However, I fear that might be too slow - any better suggestions?

Link:
box.net/shared/86de16802a

Hi, I am trying to use your code and shaders in my quest to use geometry instancing that will work on ATI cards.
The source changes compile with no issues, but using the shader gives the following:

0(11) : warning C7532: global variable gl_InstanceID requires "#version 140" or later
0(11) : warning C0000: ... or #extension GL_EXT_gpu_shader4 : enable

Are there maybe some other code changes, or something I’ve forgotten to do?
The basic-shaders-only setting doesn’t seem to make a difference either way.

I’ve got it working now with writing my own shader, the code changes seem to work nicely though. Thanks!

Sorry to dig up an old thread, but I’d like to know if these changes are included in Panda now? Either in 1.8.0, or in development builds.

They are, but there is currently a bug which breaks GLSL shaders.

What bug are you referring to teedee? I tried the GLSL instancing a few weeks ago and I got it to work on both a ATI 5450 and a GTX 260.

This one: http://bugs.launchpad.net/panda3d/+bug/912674
It might work if you use a p3d_ prefix, but not a gl_ prefix as is used in most examples.

If it’s just a matter of prefixes, then I would consider it a minor annoyance. I don’t know GLSL yet, so I’m not sure how much that changes, but from what rbd wrote here: panda3d.org/forums/viewtopi … 8114#88114 I would assume it shouldn’t be a showstopper.

Zhao, would you be so kind to share the instancing code? Or some snippets from it? I have that running in CG, but GLSL is new to me, so taking a look at how it’s done in there would help me get up to speed quicker.

Sure, no problem.

My example code is to just generate two smileys instances offsetted from each other.

The only tricks I encountered to get it to work is that 1) the shaderinput had to be set twice in slightly different ways 2) My ATI 5450 didn’t want to be compatible :stuck_out_tongue: and I had to comment out the GL_ARB compatability extension. But other than that, I had no difficulties getting it to work.

I never got the demo code posted in the messages earlier to work though. (ie., only one ralph showed up.) But the framework used there was complicated while this example hopefully is very simple to execute.

Main panda code

strVertexShader = GTMPPath() + "simple_v.glsl"
strFragmentShader = GTMPPath() + "simple_p.glsl"

myShader = Shader.load(Shader.SLGLSL, strVertexShader, strFragmentShader )

npModel = loader.loadModel('smiley')
npModel.reparentTo( render )
npModel.setShader( myShader )

npModel.showTightBounds()
npModel.setInstanceCount( 2 )

shader_data = PTA_LVecBase4f() 
shader_data.pushBack(UnalignedLVecBase4f( 1.0, 1.0, 1.0, 0.0 )) 
shader_data.pushBack(UnalignedLVecBase4f( 4.0, 4.0, 4.0, 0.0 )) 

npModel.setShaderInput('shader_data', shader_data) 
npModel.setShaderInput('shader_data[0]', shader_data) 

base.cam.setPos( 0, -20, 0 )

run()

vertex shader

//GLSL 
#version 140
#extension GL_ARB_compatibility : enable

uniform mat4 p3d_ModelViewProjectionMatrix; 
in vec4 p3d_Vertex; 
in vec4 p3d_MultiTexCoord0; 
uniform vec4 shader_data[2];

void main() {
  gl_Position = p3d_ModelViewProjectionMatrix * (p3d_Vertex + shader_data[ gl_InstanceID ] );
  gl_TexCoord[0] = p3d_MultiTexCoord0; 
}

fragment shader

//GLSL 
#version 140
#extension GL_ARB_compatibility : enable 

uniform sampler2D p3d_Texture0; 

void main() {
  gl_FragColor = texture2D(p3d_Texture0, gl_TexCoord[0].st);
}

Btw, I have to add that I didn’t find the lack of gl_prefix to be critical. Also I may be mistaken, but it seems that in more modern GLSL versions, (ie., the versions needed for instancing to work), some cards such as my ATI drops backwards compatilibity and a lot of gl_XXX wouldn’t work anyway even if Panda supported them correctly as they are only specified for early GLSL versions.

Again, I maybe wrong, but I kind of remember reading that the reason for dropping some of the gl_XXX in modern GLSL, is that input steams are treated generically so there is no official ‘vertex position’ to speak of.

Ah, that might explain why I needed to add a

#extension GL_ARB_compatibility : enable

for it to work on ATI. Maybe that is not needed if not using the gl_ prefixes.

Thanks very much for the code, Zhao :slight_smile:. Works like a charm.