diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index 3ab2157e18..cafc199a95 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx @@ -84,7 +84,9 @@ D3DMATRIX DXGraphicsStateGuardian9::_d3d_ident_mat; unsigned char *DXGraphicsStateGuardian9::_temp_buffer = NULL; unsigned char *DXGraphicsStateGuardian9::_safe_buffer_start = NULL; +#ifdef HAVE_CG LPDIRECT3DDEVICE9 DXGraphicsStateGuardian9::_cg_device = NULL; +#endif #define __D3DLIGHT_RANGE_MAX ((PN_stdfloat)sqrt(FLT_MAX)) //for some reason this is missing in dx9 hdrs @@ -150,6 +152,10 @@ DXGraphicsStateGuardian9(GraphicsEngine *engine, GraphicsPipe *pipe) : _supports_stream_offset = false; +#ifdef HAVE_CG + _cg_context = 0; +#endif + get_gamma_table(); atexit (atexit_function); } @@ -2372,6 +2378,8 @@ reset() { #ifdef HAVE_CG set_cg_device(_d3d_device); + _cg_context = cgCreateContext(); + if (cgD3D9IsProfileSupported(CG_PROFILE_PS_2_0) && cgD3D9IsProfileSupported(CG_PROFILE_VS_2_0)) { _supports_basic_shaders = true; @@ -2388,7 +2396,6 @@ reset() { } if (dxgsg9_cat.is_debug()) { - CGprofile vertex_profile; CGprofile pixel_profile; @@ -2408,8 +2415,8 @@ reset() { } dxgsg9_cat.debug() - << "\nCg vertex profile = " << vertex_profile_str << " id = " << vertex_profile - << "\nCg pixel profile = " << pixel_profile_str << " id = " << pixel_profile + << "\nCg latest vertex profile = " << vertex_profile_str << " id = " << vertex_profile + << "\nCg latest pixel profile = " << pixel_profile_str << " id = " << pixel_profile << "\nshader model = " << _shader_model << "\n"; } @@ -4152,6 +4159,12 @@ close_gsg() { //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian9:: free_nondx_resources() { +#ifdef HAVE_CG + if (_cg_context) { + cgDestroyContext(_cg_context); + _cg_context = 0; + } +#endif } //////////////////////////////////////////////////////////////////// @@ -5628,9 +5641,6 @@ set_cg_device(LPDIRECT3DDEVICE9 cg_device) { #endif // HAVE_CG } - - - typedef string KEY; typedef struct _KEY_ELEMENT diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.h b/panda/src/dxgsg9/dxGraphicsStateGuardian9.h index caa8e91769..ac242d7ff2 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.h +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.h @@ -377,7 +377,10 @@ protected: int _supports_gamma_calibration; +#ifdef HAVE_CG + CGcontext _cg_context; static LPDIRECT3DDEVICE9 _cg_device; +#endif public: virtual TypeHandle get_type() const { diff --git a/panda/src/dxgsg9/dxShaderContext9.I b/panda/src/dxgsg9/dxShaderContext9.I index 72794f752d..0eced1b511 100644 --- a/panda/src/dxgsg9/dxShaderContext9.I +++ b/panda/src/dxgsg9/dxShaderContext9.I @@ -12,6 +12,7 @@ // //////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////// // Function: DXShaderContext9::valid // Access: Public @@ -22,12 +23,10 @@ // or if no shader languages are compiled into panda. //////////////////////////////////////////////////////////////////// INLINE bool CLP(ShaderContext):: -valid (GSG *gsg) { +valid(GSG *gsg) { #ifdef HAVE_CG - if (_cg_context) { - return true; - } -#endif + return (_cg_program != 0); +#else return false; +#endif } - diff --git a/panda/src/dxgsg9/dxShaderContext9.cxx b/panda/src/dxgsg9/dxShaderContext9.cxx index 426e31a366..0e86d46c16 100644 --- a/panda/src/dxgsg9/dxShaderContext9.cxx +++ b/panda/src/dxgsg9/dxShaderContext9.cxx @@ -22,8 +22,9 @@ #include #include #include + #ifdef HAVE_CG -#include "Cg/cgD3D9.h" +#include #endif #define DEBUG_SHADER 0 @@ -37,89 +38,42 @@ TypeHandle CLP(ShaderContext)::_type_handle; //////////////////////////////////////////////////////////////////// CLP(ShaderContext):: CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { - _vertex_element_array = NULL; _vertex_declaration = NULL; _num_bound_streams = 0; - _name = s->get_filename ( ); + _name = s->get_filename(); #ifdef HAVE_CG - _cg_context = 0; + CGcontext context = DCAST(DXGraphicsStateGuardian9, gsg)->_cg_context; + if (s->get_language() == Shader::SL_Cg) { // Ask the shader to compile itself for us and // to give us the resulting Cg program objects. - - if (!s->cg_compile_for(gsg->_shader_caps, - _cg_context, - _cg_vprogram, - _cg_fprogram, - _cg_gprogram, // CG2 CHANGE - _cg_parameter_map)) { + if (!s->cg_compile_for(gsg->_shader_caps, context, + _cg_program, _cg_parameter_map)) { return; } // Load the program. - - BOOL paramater_shadowing; - DWORD assembly_flags; - - paramater_shadowing = FALSE; - assembly_flags = 0; - + DWORD assembly_flags = 0; #if DEBUG_SHADER assembly_flags |= D3DXSHADER_DEBUG; #endif HRESULT hr; bool success = true; - hr = cgD3D9LoadProgram(_cg_vprogram, paramater_shadowing, assembly_flags); + hr = cgD3D9LoadProgram(_cg_program, FALSE, assembly_flags); if (FAILED (hr)) { dxgsg9_cat.error() - << "vertex shader cgD3D9LoadProgram failed " - << D3DERRORSTRING(hr); + << "cgD3D9LoadProgram failed " << D3DERRORSTRING(hr); CGerror error = cgGetError(); if (error != CG_NO_ERROR) { dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n"; } - success = false; - } - - hr = cgD3D9LoadProgram(_cg_fprogram, paramater_shadowing, assembly_flags); - if (FAILED (hr)) { - dxgsg9_cat.error() - << "pixel shader cgD3D9LoadProgram failed " - << D3DERRORSTRING(hr); - - CGerror error = cgGetError(); - if (error != CG_NO_ERROR) { - dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n"; - } - success = false; - } - - // BEGIN CG2 CHANGE - if (_cg_gprogram != 0) - { - hr = cgD3D9LoadProgram(_cg_gprogram, paramater_shadowing, assembly_flags); - if (FAILED (hr)) { - dxgsg9_cat.error() - << "geometry shader cgD3D9LoadProgram failed " - << D3DERRORSTRING(hr); - - CGerror error = cgGetError(); - if (error != CG_NO_ERROR) { - dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n"; - } - success = false; - } - } - // END CG2 CHANGE - - if (!success) { release_resources(); } } @@ -203,12 +157,9 @@ CLP(ShaderContext):: void CLP(ShaderContext):: release_resources() { #ifdef HAVE_CG - if (_cg_context) { - cgDestroyContext(_cg_context); - _cg_context = 0; - _cg_vprogram = 0; - _cg_fprogram = 0; - _cg_gprogram = 0; // CG2 CHANGE + if (_cg_program) { + cgDestroyProgram(_cg_program); + _cg_program = 0; _cg_parameter_map.clear(); } #endif @@ -228,11 +179,10 @@ release_resources() { bool CLP(ShaderContext):: bind(GSG *gsg) { - bool bind_state; + bool bind_state = false; - bind_state = false; #ifdef HAVE_CG - if (_cg_context) { + if (_cg_program) { // clear the last cached FVF to make sure the next SetFVF call goes through gsg -> _last_fvf = 0; @@ -244,9 +194,9 @@ bind(GSG *gsg) { // Bind the shaders. bind_state = true; - hr = cgD3D9BindProgram(_cg_vprogram); + hr = cgD3D9BindProgram(_cg_program); if (FAILED (hr)) { - dxgsg9_cat.error() << "cgD3D9BindProgram vertex shader failed " << D3DERRORSTRING(hr); + dxgsg9_cat.error() << "cgD3D9BindProgram failed " << D3DERRORSTRING(hr); CGerror error = cgGetError(); if (error != CG_NO_ERROR) { @@ -255,34 +205,6 @@ bind(GSG *gsg) { bind_state = false; } - hr = cgD3D9BindProgram(_cg_fprogram); - if (FAILED (hr)) { - dxgsg9_cat.error() << "cgD3D9BindProgram pixel shader failed " << D3DERRORSTRING(hr); - - CGerror error = cgGetError(); - if (error != CG_NO_ERROR) { - dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n"; - } - - bind_state = false; - } - - // BEGIN CG2 CHANGE - if (_cg_gprogram != 0) - { - hr = cgD3D9BindProgram(_cg_gprogram); - if (FAILED (hr)) { - dxgsg9_cat.error() << "cgD3D9BindProgram geometry shader failed " << D3DERRORSTRING(hr); - - CGerror error = cgGetError(); - if (error != CG_NO_ERROR) { - dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n"; - } - - bind_state = false; - } - } - // END CG2 CHANGE } #endif @@ -298,18 +220,12 @@ void CLP(ShaderContext):: unbind(GSG *gsg) { #ifdef HAVE_CG - if (_cg_context) { + if (_cg_program) { HRESULT hr; - - hr = gsg -> _d3d_device -> SetVertexShader (NULL); - if (FAILED (hr)) { + hr = cgD3D9UnbindProgram(_cg_program); + if (FAILED(hr)) { dxgsg9_cat.error() - << "SetVertexShader (NULL) failed " << D3DERRORSTRING(hr); - } - hr = gsg -> _d3d_device -> SetPixelShader (NULL); - if (FAILED (hr)) { - dxgsg9_cat.error() - << "SetPixelShader (NULL) failed " << D3DERRORSTRING(hr); + << "cgD3D9UnbindProgram failed " << D3DERRORSTRING(hr); } } #endif @@ -339,10 +255,9 @@ InternalName *global_internal_name_1 = 0; #endif void CLP(ShaderContext):: -issue_parameters(GSG *gsg, int altered) -{ +issue_parameters(GSG *gsg, int altered) { #ifdef HAVE_CG - if (_cg_context) { + if (_cg_program) { // Iterate through _ptr parameters for (int i=0; i<(int)_shader->_ptr_spec.size(); i++) { @@ -510,7 +425,7 @@ bool CLP(ShaderContext):: update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg, bool force) { if (prev) prev->disable_shader_vertex_arrays(gsg); #ifdef HAVE_CG - if (!_cg_context) { + if (!_cg_program) { return true; } @@ -717,11 +632,11 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg, bool force) { if (( _vertex_element_array != NULL ) && ( _vertex_element_array->add_end_vertex_element() != false )) { - if ( dxgsg9_cat.is_debug() ) { + if (dxgsg9_cat.is_debug()) { // Note that the currently generated vertex declaration works but never validates. // My theory is that this is due to the shader programs always using float4 whereas // the vertex declaration correctly sets the number of inputs (float2, float3, etc.). - if (cgD3D9ValidateVertexDeclaration(_cg_vprogram, + if (cgD3D9ValidateVertexDeclaration(_cg_program, _vertex_element_array->_vertex_element_array) == CG_TRUE) { dxgsg9_cat.debug() << "cgD3D9ValidateVertexDeclaration succeeded\n"; } else { @@ -763,7 +678,7 @@ void CLP(ShaderContext):: disable_shader_texture_bindings(GSG *gsg) { #ifdef HAVE_CG - if (_cg_context) { + if (_cg_program) { for (int i=0; i<(int)_shader->_tex_spec.size(); i++) { CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno]; if (p == NULL) { @@ -803,7 +718,7 @@ update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg) if (prev) prev->disable_shader_texture_bindings(gsg); #ifdef HAVE_CG - if (_cg_context) { + if (_cg_program) { for (int i=0; i<(int)_shader->_tex_spec.size(); i++) { CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno]; diff --git a/panda/src/dxgsg9/dxShaderContext9.h b/panda/src/dxgsg9/dxShaderContext9.h index 41424f38db..c680443268 100644 --- a/panda/src/dxgsg9/dxShaderContext9.h +++ b/panda/src/dxgsg9/dxShaderContext9.h @@ -22,11 +22,9 @@ #include "shader.h" #include "shaderContext.h" - #define CLP(name) DX##name##9 #define CLASSPREFIX_QUOTED "DX" - class VertexElementArray; class CLP(GraphicsStateGuardian); @@ -41,7 +39,7 @@ class CLP(GraphicsStateGuardian); // D3DXCONSTANT_DESC *constant_description_array; // } // DX_PARAMETER; -// +// // typedef struct // { // int state; @@ -52,7 +50,7 @@ class CLP(GraphicsStateGuardian); // }; // LPD3DXCONSTANTTABLE constant_table; // D3DXCONSTANTTABLE_DESC constant_table_description; -// +// // int total_semantics; // D3DXSEMANTIC *semantic_array; // } @@ -62,11 +60,10 @@ class CLP(GraphicsStateGuardian); // Class : DXShaderContext9 // Description : xyz //////////////////////////////////////////////////////////////////// - -class EXPCL_PANDADX CLP(ShaderContext): public ShaderContext { +class EXPCL_PANDADX CLP(ShaderContext) : public ShaderContext { public: typedef CLP(GraphicsStateGuardian) GSG; - + CLP(ShaderContext)(Shader *s, GSG *gsg); ~CLP(ShaderContext)(); @@ -88,23 +85,14 @@ public: // FOR DEBUGGING string _name; - + private: - #ifdef HAVE_CG - CGcontext _cg_context; - CGprogram _cg_vprogram; - CGprogram _cg_fprogram; - - // BEGIN CG2 CHANGE - CGprogram _cg_gprogram; // Geometry program - // END CG2 CHANGE - + CGprogram _cg_program; pvector _cg_parameter_map; #endif private: - void release_resources(void); public: diff --git a/panda/src/glstuff/glCgShaderContext_src.I b/panda/src/glstuff/glCgShaderContext_src.I index c989f99b63..243ed4c758 100755 --- a/panda/src/glstuff/glCgShaderContext_src.I +++ b/panda/src/glstuff/glCgShaderContext_src.I @@ -27,8 +27,7 @@ INLINE bool CLP(CgShaderContext):: valid() { if (_shader->get_error_flag()) return false; if (_shader->get_language() != Shader::SL_Cg) return false; - if (_cg_context) return true; - return false; + return (_cg_program != 0); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/glstuff/glCgShaderContext_src.cxx b/panda/src/glstuff/glCgShaderContext_src.cxx index c73659eda9..cb7d50678e 100755 --- a/panda/src/glstuff/glCgShaderContext_src.cxx +++ b/panda/src/glstuff/glCgShaderContext_src.cxx @@ -40,63 +40,40 @@ TypeHandle CLP(CgShaderContext)::_type_handle; CLP(CgShaderContext):: CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext(s) { _glgsg = glgsg; - _cg_context = 0; - _cg_vprogram = 0; - _cg_fprogram = 0; - _cg_gprogram = 0; - _cg_vprofile = CG_PROFILE_UNKNOWN; - _cg_fprofile = CG_PROFILE_UNKNOWN; - _cg_gprofile = CG_PROFILE_UNKNOWN; + _cg_program = 0; + _glsl_profile = false; nassertv(s->get_language() == Shader::SL_Cg); + CGcontext context = _glgsg->_cg_context; + // Ask the shader to compile itself for us and // to give us the resulting Cg program objects. - if (!s->cg_compile_for(_glgsg->_shader_caps, - _cg_context, - _cg_vprogram, - _cg_fprogram, - _cg_gprogram, - _cg_parameter_map)) { + if (!s->cg_compile_for(_glgsg->_shader_caps, context, + _cg_program, _cg_parameter_map)) { return; } // Load the program. - if (_cg_vprogram != 0) { - _cg_vprofile = cgGetProgramProfile(_cg_vprogram); - cgGLLoadProgram(_cg_vprogram); - CGerror verror = cgGetError(); - if (verror != CG_NO_ERROR) { - const char *str = cgGetErrorString(verror); - GLCAT.error() - << "Could not load Cg vertex program: " << s->get_filename(Shader::ST_vertex) - << " (" << cgGetProfileString(_cg_vprofile) << " " << str << ")\n"; - release_resources(); - } - } + if (_cg_program == 0) { + const char *str = cgGetErrorString(cgGetError()); + GLCAT.error() + << "Could not combine Cg program: " << s->get_filename() + << " (" << str << ")\n"; + release_resources(); - if (_cg_fprogram != 0) { - _cg_fprofile = cgGetProgramProfile(_cg_fprogram); - cgGLLoadProgram(_cg_fprogram); - CGerror ferror = cgGetError(); - if (ferror != CG_NO_ERROR) { - const char *str = cgGetErrorString(ferror); - GLCAT.error() - << "Could not load Cg fragment program: " << s->get_filename(Shader::ST_fragment) - << " (" << cgGetProfileString(_cg_fprofile) << " " << str << ")\n"; - release_resources(); + } else { + if (cgGetProgramProfile(_cg_program) == CG_PROFILE_GLSLC) { + _glsl_profile = true; } - } - if (_cg_gprogram != 0) { - _cg_gprofile = cgGetProgramProfile(_cg_gprogram); - cgGLLoadProgram(_cg_gprogram); - CGerror gerror = cgGetError(); - if (gerror != CG_NO_ERROR) { - const char *str = cgGetErrorString(gerror); + cgGLLoadProgram(_cg_program); + CGerror error = cgGetError(); + if (error != CG_NO_ERROR) { + const char *str = cgGetErrorString(error); GLCAT.error() - << "Could not load Cg geometry program: " << s->get_filename(Shader::ST_geometry) - << " (" << cgGetProfileString(_cg_gprofile) << " " << str << ")\n"; + << "Could not load program: " << s->get_filename() + << " (" << str << ")\n"; release_resources(); } } @@ -122,20 +99,14 @@ CLP(CgShaderContext):: //////////////////////////////////////////////////////////////////// void CLP(CgShaderContext):: release_resources() { - if (_cg_context) { - cgDestroyContext(_cg_context); - _cg_context = 0; - // Do *NOT* destroy the programs here! It causes problems. -// if (_cg_vprogram != 0) cgDestroyProgram(_cg_vprogram); -// if (_cg_fprogram != 0) cgDestroyProgram(_cg_fprogram); -// if (_cg_gprogram != 0) cgDestroyProgram(_cg_gprogram); - _cg_vprogram = 0; - _cg_fprogram = 0; - _cg_gprogram = 0; - _cg_parameter_map.clear(); + if (_cg_program != 0) { + cgDestroyProgram(_cg_program); + _cg_program = 0; } + _cg_parameter_map.clear(); if (_glgsg) { _glgsg->report_my_gl_errors(); + } else if (glGetError() != GL_NO_ERROR) { GLCAT.error() << "GL error in ShaderContext destructor\n"; } @@ -155,25 +126,15 @@ release_resources() { //////////////////////////////////////////////////////////////////// void CLP(CgShaderContext):: bind(bool reissue_parameters) { - if (reissue_parameters) { - // Pass in k-parameters and transform-parameters - issue_parameters(Shader::SSD_general); - } + if (_cg_program != 0) { + if (reissue_parameters) { + // Pass in k-parameters and transform-parameters + issue_parameters(Shader::SSD_general); + } - if (_cg_context != 0) { // Bind the shaders. - if (_cg_vprogram != 0) { - cgGLEnableProfile(_cg_vprofile); - cgGLBindProgram(_cg_vprogram); - } - if (_cg_fprogram != 0) { - cgGLEnableProfile(_cg_fprofile); - cgGLBindProgram(_cg_fprogram); - } - if (_cg_gprogram != 0) { - cgGLEnableProfile(_cg_gprofile); - cgGLBindProgram(_cg_gprogram); - } + cgGLEnableProgramProfiles(_cg_program); + cgGLBindProgram(_cg_program); cg_report_errors(); _glgsg->report_my_gl_errors(); @@ -187,18 +148,12 @@ bind(bool reissue_parameters) { //////////////////////////////////////////////////////////////////// void CLP(CgShaderContext):: unbind() { - if (_cg_context != 0) { - if (_cg_vprogram != 0) { - cgGLUnbindProgram(_cg_vprofile); - cgGLDisableProfile(_cg_vprofile); - } - if (_cg_fprogram != 0) { - cgGLUnbindProgram(_cg_fprofile); - cgGLDisableProfile(_cg_fprofile); - } - if (_cg_gprogram != 0) { - cgGLUnbindProgram(_cg_gprofile); - cgGLDisableProfile(_cg_gprofile); + if (_cg_program != 0) { + int num_domains = cgGetNumProgramDomains(_cg_program); + for (int i = 0; i < num_domains; ++i) { + CGprofile profile = cgGetProgramDomainProfile(_cg_program, i); + cgGLUnbindProgram(profile); + cgGLDisableProfile(profile); } cg_report_errors(); @@ -396,7 +351,25 @@ disable_shader_vertex_arrays() { for (int i=0; i<(int)_shader->_var_spec.size(); i++) { CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno]; if (p == 0) continue; - cgGLDisableClientState(p); + + if (_glsl_profile && cgGetParameterBaseResource(p) == CG_ATTR0) { + int index = cgGetParameterResourceIndex(p); + if (index >= 8) { + _glgsg->_glClientActiveTexture(GL_TEXTURE0 + (index - 8)); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + } else if (index == 0) { + glDisableClientState(GL_VERTEX_ARRAY); + + } else if (index == 2) { + glDisableClientState(GL_NORMAL_ARRAY); + + } else if (index == 3) { + glDisableClientState(GL_COLOR_ARRAY); + } + } else { + cgGLDisableClientState(p); + } } cg_report_errors(); @@ -464,20 +437,68 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) { CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno]; if (numeric_type == GeomEnums::NT_packed_dabc) { - cgGLSetParameterPointer(p, GL_BGRA, GL_UNSIGNED_BYTE, - stride, client_pointer + start); + // Yes, this is a thing. + num_values = GL_BGRA; + } + + // This is truly the most preposterous hack. When using the GLSL + // profiles, cgGLSetParameterPointer relies on the the driver mapping + // standard attributes to fixed indices (and breaking the spec doing + // so), which only the NVIDIA drivers do. Unbelievable. + if (_glsl_profile && cgGetParameterBaseResource(p) == CG_ATTR0) { + int index = cgGetParameterResourceIndex(p); + switch (index) { + case 0: // gl_Vertex + glVertexPointer(num_values, _glgsg->get_numeric_type(numeric_type), + stride, client_pointer + start); + glEnableClientState(GL_VERTEX_ARRAY); + break; + + case 2: // gl_Normal + glNormalPointer(_glgsg->get_numeric_type(numeric_type), + stride, client_pointer + start); + glEnableClientState(GL_NORMAL_ARRAY); + break; + + case 3: // gl_Color + glColorPointer(num_values, _glgsg->get_numeric_type(numeric_type), + stride, client_pointer + start); + glEnableClientState(GL_COLOR_ARRAY); + break; + + case 4: // gl_SecondaryColor + //glSecondaryColorPointer(num_values, _glgsg->get_numeric_type(numeric_type), + // stride, client_pointer + start); + //glEnableClientState(GL_SECONDARY_COLOR_ARRAY); + //break; + case 5: // gl_FogCoord + case 6: // PSIZE? + case 7: // BLENDINDICES? + case 1: // glWeightPointerARB? + GLCAT.error() + << "Unable to bind " << *name << " to " + << cgGetParameterResourceName(p) << "\n"; + break; + + default: + _glgsg->_glClientActiveTexture(GL_TEXTURE0 + (index - 8)); + glTexCoordPointer(num_values, _glgsg->get_numeric_type(numeric_type), + stride, client_pointer + start); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + break; + } } else { if (name == InternalName::get_normal() && num_values == 4) { - // In some cases, the normals are aligned to 4 values. - // This would cause an error on some rivers, so we tell it - // to use the first three values only. + // In some cases, the normals are aligned to 4 values. We tell + // it to use three values exactly, otherwise we get the error: + // An unsupported GL extension was required to perform this operation. num_values = 3; } - cgGLSetParameterPointer(p, - num_values, _glgsg->get_numeric_type(numeric_type), + cgGLSetParameterPointer(p, num_values, + _glgsg->get_numeric_type(numeric_type), stride, client_pointer + start); + cgGLEnableClientState(p); } - cgGLEnableClientState(p); } else { CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno]; cgGLDisableClientState(p); @@ -506,6 +527,7 @@ disable_shader_texture_bindings() { for (int i=0; i<(int)_shader->_tex_spec.size(); i++) { CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno]; if (p == 0) continue; + int texunit = cgGetParameterResourceIndex(p); _glgsg->_glActiveTexture(GL_TEXTURE0 + texunit); @@ -527,7 +549,7 @@ disable_shader_texture_bindings() { glBindTexture(GL_TEXTURE_CUBE_MAP, 0); } // This is probably faster - but maybe not as safe? - // cgGLDisableTextureParameter(p); + //cgGLDisableTextureParameter(p); } #endif // OPENGLES_2 diff --git a/panda/src/glstuff/glCgShaderContext_src.h b/panda/src/glstuff/glCgShaderContext_src.h index 3e487fbe04..b5d45d4aaa 100755 --- a/panda/src/glstuff/glCgShaderContext_src.h +++ b/panda/src/glstuff/glCgShaderContext_src.h @@ -1,4 +1,4 @@ -// Filename: glShaderContext_src.h +// Filename: glCgShaderContext_src.h // Created by: jyelon (01Sep05) // //////////////////////////////////////////////////////////////////// @@ -51,15 +51,10 @@ public: INLINE bool uses_custom_texture_bindings(void); private: - CGcontext _cg_context; - CGprogram _cg_vprogram; - CGprogram _cg_fprogram; - CGprogram _cg_gprogram; - CGprofile _cg_vprofile; - CGprofile _cg_fprofile; - CGprofile _cg_gprofile; + CGprogram _cg_program; + bool _glsl_profile; - pvector _cg_parameter_map; + pvector _cg_parameter_map; CLP(GraphicsStateGuardian) *_glgsg; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 877440e148..6e800d4b0a 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -318,6 +318,10 @@ CLP(GraphicsStateGuardian)(GraphicsEngine *engine, GraphicsPipe *pipe) : _scissor_enabled = false; _scissor_attrib_active = false; +#ifdef HAVE_CG + _cg_context = 0; +#endif + #ifdef DO_PSTATS if (gl_finish) { GLCAT.warning() @@ -1083,15 +1087,19 @@ reset() { _supports_depth_texture = true; } - if (_supports_depth_texture && + if (gl_support_shadow_filter && + _supports_depth_texture && has_extension("GL_ARB_shadow") && has_extension("GL_ARB_fragment_program_shadow")) { _supports_shadow_filter = true; } - if (_gl_vendor.substr(0,3)=="ATI") { + // Actually, we can't keep forever disabling ARB_shadow on ATI cards, + // since they do work correctly now. Maybe there is some feature + // level we can check somewhere? + /*if (_gl_vendor.substr(0,3)=="ATI") { // ATI drivers have never provided correct shadow support. _supports_shadow_filter = false; - } + }*/ _supports_texture_combine = has_extension("GL_ARB_texture_env_combine") || is_at_least_gl_version(1, 3) || is_at_least_gles_version(1, 1); @@ -1156,30 +1164,37 @@ reset() { // cgGLGetLatestProfile doesn't seem to return anything other // arbvp1/arbfp1 on non-NVIDIA cards, which is severely limiting. - // Actually, it seems that these profiles are horribly broken on these - // cards. Let's not do this. - //if ((_shader_caps._active_vprofile == CG_PROFILE_ARBVP1 || - // _shader_caps._active_fprofile == CG_PROFILE_ARBFP1) && - // cgGLIsProfileSupported(CG_PROFILE_GLSLV) && - // cgGLIsProfileSupported(CG_PROFILE_GLSLF)) { + // So, if this happens, we set it to GLSL, which is + // usually supported on all cards. + // The GLSL profiles are horribly broken on non-NVIDIA cards, but + // I think I've worked around the issues sufficiently. + if ((_shader_caps._active_vprofile == CG_PROFILE_ARBVP1 || + _shader_caps._active_fprofile == CG_PROFILE_ARBFP1) && + cgGLIsProfileSupported(CG_PROFILE_GLSLV) && + cgGLIsProfileSupported(CG_PROFILE_GLSLF)) { - // // So, if this happens, we set it to GLSL, which is - // // usually supported on all cards. - // _shader_caps._active_vprofile = (int)CG_PROFILE_GLSLV; - // _shader_caps._active_fprofile = (int)CG_PROFILE_GLSLF; + _shader_caps._active_vprofile = (int)CG_PROFILE_GLSLV; + _shader_caps._active_fprofile = (int)CG_PROFILE_GLSLF; #if CG_VERSION_NUM >= 2200 - // if (cgGLIsProfileSupported(CG_PROFILE_GLSLG)) { - // _shader_caps._active_gprofile = (int)CG_PROFILE_GLSLG; - // } + if (cgGLIsProfileSupported(CG_PROFILE_GLSLG)) { + _shader_caps._active_gprofile = (int)CG_PROFILE_GLSLG; + } #endif - //} + } } _shader_caps._ultimate_vprofile = (int)CG_PROFILE_VP40; _shader_caps._ultimate_fprofile = (int)CG_PROFILE_FP40; _shader_caps._ultimate_gprofile = (int)CG_PROFILE_GPU_GP; - _glBindProgram = (PFNGLBINDPROGRAMARBPROC) - get_extension_func("glBindProgramARB"); + _cg_context = cgCreateContext(); + +#if CG_VERSION_NUM >= 3100 + // This just sounds like a good thing to do. + cgGLSetContextGLSLVersion(_cg_context, cgGLDetectGLSLVersion()); + if (_shader_caps._active_vprofile == CG_PROFILE_GLSLV) { + cgGLSetContextOptimalOptions(_cg_context, CG_PROFILE_GLSLC); + } +#endif // Bug workaround for radeons. if (_shader_caps._active_fprofile == CG_PROFILE_ARBFP1) { @@ -2244,9 +2259,17 @@ reset() { } #endif // CG_VERSION_NUM >= 2200 +#if CG_VERSION_NUM >= 3100 + if (GLCAT.is_debug()) { + CGGLglslversion ver = cgGLGetContextGLSLVersion(_cg_context); + GLCAT.debug() + << "Cg GLSL version: " << cgGLGetGLSLVersionString(ver) << "\n"; + } +#endif + GLCAT.debug() - << "\nCg vertex profile = " << cgGetProfileString(vertex_profile) << " id = " << vertex_profile - << "\nCg pixel profile = " << cgGetProfileString(pixel_profile) << " id = " << pixel_profile + << "\nCg latest vertex profile = " << cgGetProfileString(vertex_profile) << " id = " << vertex_profile + << "\nCg latest pixel profile = " << cgGetProfileString(pixel_profile) << " id = " << pixel_profile << "\nshader model = " << _shader_model << "\n"; } @@ -2591,6 +2614,7 @@ clear_before_callback() { // texture stage is still set to stage 0. CEGUI, in particular, // makes this assumption. _glActiveTexture(GL_TEXTURE0); + _glClientActiveTexture(GL_TEXTURE0); // Clear the bound sampler object, so that we do not inadvertently // override the callback's desired sampler settings. @@ -9009,6 +9033,12 @@ set_state_and_transform(const RenderState *target, //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: free_pointers() { +#ifdef HAVE_CG + if (_cg_context != 0) { + cgDestroyContext(_cg_context); + _cg_context = 0; + } +#endif } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 4895feced0..97efe35586 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -568,6 +568,10 @@ protected: static PT(Shader) _default_shader; #endif +#ifdef HAVE_CG + CGcontext _cg_context; +#endif + #ifdef SUPPORT_IMMEDIATE_MODE CLP(ImmediateModeSender) _sender; bool _use_sender; diff --git a/panda/src/glstuff/glmisc_src.cxx b/panda/src/glstuff/glmisc_src.cxx index ae6af9b740..9ea8411923 100644 --- a/panda/src/glstuff/glmisc_src.cxx +++ b/panda/src/glstuff/glmisc_src.cxx @@ -265,6 +265,13 @@ ConfigVariableBool gl_support_sampler_objects "objects. Set to false if you suspect a bug in the " "driver implementation.")); +ConfigVariableBool gl_support_shadow_filter + ("gl-support-shadow-filter", true, + PRC_DESC("Disable this if you suspect a bug in the driver " + "implementation of ARB_shadow. Particularly, older ATI " + "cards suffered from a broken implementation of the " + "shadow map filtering features.")); + extern ConfigVariableBool gl_parallel_arrays; void CLP(init_classes)() { diff --git a/panda/src/glstuff/glmisc_src.h b/panda/src/glstuff/glmisc_src.h index 1cd46f68db..02f093a6c5 100644 --- a/panda/src/glstuff/glmisc_src.h +++ b/panda/src/glstuff/glmisc_src.h @@ -74,6 +74,7 @@ extern ConfigVariableBool gl_enable_memory_barriers; extern ConfigVariableBool gl_vertex_array_objects; extern ConfigVariableBool gl_support_primitive_restart_index; extern ConfigVariableBool gl_support_sampler_objects; +extern ConfigVariableBool gl_support_shadow_filter; extern EXPCL_GL void CLP(init_classes)(); diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index bd52784245..b814a23fde 100755 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -27,6 +27,7 @@ TypeHandle Shader::_type_handle; Shader::ShaderTable Shader::_load_table; Shader::ShaderTable Shader::_make_table; Shader::ShaderCaps Shader::_default_caps; +CGcontext Shader::_cg_context = 0; int Shader::_shaders_generated; ShaderUtilization Shader::_shader_utilization = SUT_unspecified; @@ -480,46 +481,54 @@ cp_optimize_mat_spec(ShaderMatSpec &spec) { // Access: Public // Description: //////////////////////////////////////////////////////////////////// -void Shader::cg_recurse_parameters(CGparameter parameter, - const ShaderType& type, bool& success) { +void Shader:: +cg_recurse_parameters(CGparameter parameter, const ShaderType &type, + bool &success) { - if (parameter == 0) + if (parameter == 0) { return; + } do { - int arg_dim[] = {1,0,0}; - ShaderArgDir arg_dir = cg_parameter_dir(parameter); - ShaderArgType arg_type = cg_parameter_type(parameter); - ShaderArgClass arg_class = cg_parameter_class(parameter); - ShaderArgClass arg_subclass = arg_class; + if (cgIsParameterReferenced(parameter)) { + int arg_dim[] = {1,0,0}; + ShaderArgDir arg_dir = cg_parameter_dir(parameter); + ShaderArgType arg_type = cg_parameter_type(parameter); + ShaderArgClass arg_class = cg_parameter_class(parameter); + ShaderArgClass arg_subclass = arg_class; - CGenum vbl = cgGetParameterVariability(parameter); + CGenum vbl = cgGetParameterVariability(parameter); - if ((vbl==CG_VARYING)||(vbl==CG_UNIFORM)) { - switch (cgGetParameterType(parameter)) { - case CG_STRUCT: - cg_recurse_parameters( - cgGetFirstStructParameter(parameter), type, success); - break; + if ((vbl==CG_VARYING)||(vbl==CG_UNIFORM)) { + switch (cgGetParameterType(parameter)) { + case CG_STRUCT: + cg_recurse_parameters( + cgGetFirstStructParameter(parameter), type, success); + break; - case CG_ARRAY: - arg_type = cg_parameter_type(cgGetArrayParameter(parameter, 0)); - arg_subclass = cg_parameter_class(cgGetArrayParameter(parameter, 0)); + case CG_ARRAY: + arg_type = cg_parameter_type(cgGetArrayParameter(parameter, 0)); + arg_subclass = cg_parameter_class(cgGetArrayParameter(parameter, 0)); - arg_dim[0] = cgGetArraySize(parameter, 0); + arg_dim[0] = cgGetArraySize(parameter, 0); - default: { - arg_dim[1] = cgGetParameterRows(parameter); - arg_dim[2] = cgGetParameterColumns(parameter); + default: { + arg_dim[1] = cgGetParameterRows(parameter); + arg_dim[2] = cgGetParameterColumns(parameter); - ShaderArgId id; - id._name = cgGetParameterName(parameter); - id._type = type; - id._seqno = -1; - success &= compile_parameter(id, arg_class, arg_subclass, arg_type, - arg_dir, (vbl == CG_VARYING), arg_dim, gobj_cat.get_safe_ptr()); break; + ShaderArgId id; + id._name = cgGetParameterName(parameter); + id._type = type; + id._seqno = -1; + success &= compile_parameter(id, arg_class, arg_subclass, arg_type, + arg_dir, (vbl == CG_VARYING), arg_dim, gobj_cat.get_safe_ptr()); break; + } } } + } else if (gobj_cat.is_debug()) { + gobj_cat.debug() + << "Parameter " << cgGetParameterName(parameter) + << " is unreferenced within shader " << get_filename(type) << "\n"; } } while((parameter = cgGetNextParameter(parameter))!= 0); } @@ -1375,10 +1384,6 @@ cg_release_resources() { cgDestroyProgram(_cg_gprogram); _cg_gprogram = 0; } - if (_cg_context != 0) { - cgDestroyContext(_cg_context); - _cg_context = 0; - } } //////////////////////////////////////////////////////////////////// @@ -1387,7 +1392,8 @@ cg_release_resources() { // Description: xyz //////////////////////////////////////////////////////////////////// CGprogram Shader:: -cg_compile_entry_point(const char *entry, const ShaderCaps &caps, ShaderType type) { +cg_compile_entry_point(const char *entry, const ShaderCaps &caps, + CGcontext context, ShaderType type) { CGprogram prog; CGerror err; const char *compiler_args[100]; @@ -1457,7 +1463,7 @@ cg_compile_entry_point(const char *entry, const ShaderCaps &caps, ShaderType typ } // Compile the shader with the active profile. - prog = cgCreateProgram(_cg_context, CG_SOURCE, text.c_str(), + prog = cgCreateProgram(context, CG_SOURCE, text.c_str(), (CGprofile)active, entry, (const char **)compiler_args); err = cgGetError(); if (err == CG_NO_ERROR) { @@ -1479,30 +1485,35 @@ cg_compile_entry_point(const char *entry, const ShaderCaps &caps, ShaderType typ } // The active profile failed, so recompile it with the ultimate profile. - prog = cgCreateProgram(_cg_context, CG_SOURCE, text.c_str(), + prog = cgCreateProgram(context, CG_SOURCE, text.c_str(), (CGprofile)ultimate, entry, (const char **)NULL); + + // Extract the output listing. err = cgGetError(); + const char *listing = cgGetLastListing(context); + + if (err == CG_NO_ERROR && listing != NULL && strlen(listing) > 1) { + gobj_cat.warning() + << "Encountered warnings during compilation of " << get_filename(type) + << ":\n" << listing; + + } else if (err == CG_COMPILER_ERROR) { + gobj_cat.error() + << "Failed to compile Cg shader " << get_filename(type); + if (listing != NULL) { + gobj_cat.error(false) << ":\n" << listing; + } else { + gobj_cat.error(false) << "!\n"; + } + } + if (err == CG_NO_ERROR) { return prog; } - if (err == CG_COMPILER_ERROR) { - // A compiler error has occurred. Extract the error messages. - string listing = cgGetLastListing(_cg_context); - vector_string errlines; - tokenize(listing, errlines, "\n"); - for (int i = 0; i < (int) errlines.size(); ++i) { - string line = trim(errlines[i]); - if (line != "") { - gobj_cat.error() << get_filename(type) << ": " << errlines[i] << "\n"; - } - } - } else { - gobj_cat.error() << get_filename(type) << ": " << cgGetErrorString(err) << "\n"; - } + if (prog != 0) { cgDestroyProgram(prog); } - return 0; } @@ -1514,29 +1525,11 @@ cg_compile_entry_point(const char *entry, const ShaderCaps &caps, ShaderType typ // variables _cg_context, _cg_vprogram, _cg_fprogram. //////////////////////////////////////////////////////////////////// bool Shader:: -cg_compile_shader(const ShaderCaps &caps) { - - // If we already tried compiling for this set of caps, there's no point - // trying again. Just return the results of the previous compile. - if (caps == _cg_last_caps) { - if (_cg_context == 0) { - return false; - } else { - return true; - } - } - +cg_compile_shader(const ShaderCaps &caps, CGcontext context) { _cg_last_caps = caps; - _cg_context = cgCreateContext(); - - if (_cg_context == 0) { - gobj_cat.error() << "Could not create a Cg context object.\n"; - return false; - } - if (!_text._separate || !_text._vertex.empty()) { - _cg_vprogram = cg_compile_entry_point("vshader", caps, ST_vertex); + _cg_vprogram = cg_compile_entry_point("vshader", caps, context, ST_vertex); if (_cg_vprogram == 0) { cg_release_resources(); return false; @@ -1545,7 +1538,7 @@ cg_compile_shader(const ShaderCaps &caps) { } if (!_text._separate || !_text._fragment.empty()) { - _cg_fprogram = cg_compile_entry_point("fshader", caps, ST_fragment); + _cg_fprogram = cg_compile_entry_point("fshader", caps, context, ST_fragment); if (_cg_fprogram == 0) { cg_release_resources(); return false; @@ -1554,7 +1547,7 @@ cg_compile_shader(const ShaderCaps &caps) { } if ((_text._separate && !_text._geometry.empty()) || (!_text._separate && _text._shared.find("gshader") != string::npos)) { - _cg_gprogram = cg_compile_entry_point("gshader", caps, ST_geometry); + _cg_gprogram = cg_compile_entry_point("gshader", caps, context, ST_geometry); if (_cg_gprogram == 0) { cg_release_resources(); return false; @@ -1606,7 +1599,7 @@ bool Shader:: cg_analyze_entry_point(CGprogram prog, ShaderType type) { bool success = true; - cg_recurse_parameters(cgGetFirstParameter(prog, CG_PROGRAM),type,success); + cg_recurse_parameters(cgGetFirstParameter(prog, CG_PROGRAM), type, success); return success; } @@ -1645,7 +1638,18 @@ cg_analyze_entry_point(CGprogram prog, ShaderType type) { bool Shader:: cg_analyze_shader(const ShaderCaps &caps) { - if (!cg_compile_shader(caps)) { + // Make sure we have a context for analyzing the shader. + if (_cg_context == 0) { + _cg_context = cgCreateContext(); + if (_cg_context == 0) { + gobj_cat.error() + << "Could not create a Cg context object: " + << cgGetErrorString(cgGetError()) << "\n"; + return false; + } + } + + if (!cg_compile_shader(caps, _cg_context)) { return false; } @@ -1805,26 +1809,18 @@ cg_program_from_shadertype(ShaderType type) { // longer own them. //////////////////////////////////////////////////////////////////// bool Shader:: -cg_compile_for(const ShaderCaps &caps, - CGcontext &ctx, - CGprogram &vprogram, - CGprogram &fprogram, - CGprogram &gprogram, - pvector &map) { +cg_compile_for(const ShaderCaps &caps, CGcontext context, + CGprogram &combined_program, pvector &map) { // Initialize the return values to empty. - ctx = 0; - vprogram = 0; - fprogram = 0; - gprogram = 0; - + combined_program = 0; map.clear(); // Make sure the shader is compiled for the target caps. // Most of the time, it will already be - this is usually a no-op. _default_caps = caps; - if (!cg_compile_shader(caps)) { + if (!cg_compile_shader(caps, context)) { return false; } @@ -1850,8 +1846,24 @@ cg_compile_for(const ShaderCaps &caps, return false; } - // Build a parameter map. + // Gather the programs we will be combining. + pvector programs; + if (_cg_vprogram != 0) { + programs.push_back(_cg_vprogram); + } + if (_cg_fprogram != 0) { + programs.push_back(_cg_fprogram); + } + if (_cg_gprogram != 0) { + programs.push_back(_cg_gprogram); + } + // Combine the programs. This can be more optimal than loading them + // individually, and it is even necessary for some profiles + // (particularly GLSL profiles on non-NVIDIA GPUs). + combined_program = cgCombinePrograms(programs.size(), &programs[0]); + + // Build a parameter map. int n_mat = (int)_mat_spec.size(); int n_tex = (int)_tex_spec.size(); int n_var = (int)_var_spec.size(); @@ -1859,46 +1871,103 @@ cg_compile_for(const ShaderCaps &caps, map.resize(n_mat + n_tex + n_var + n_ptr); - for (int i=0; i &map); + bool cg_compile_for(const ShaderCaps &caps, CGcontext context, + CGprogram &combined_program, pvector &map); #endif