This fixes most issues with Cg's GLSL profiles on non-NVIDIA cards

This commit is contained in:
rdb 2015-02-02 16:31:23 +01:00
parent 3aefaff8b1
commit 3b1bd9ef39
14 changed files with 434 additions and 394 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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
}

View File

@ -22,8 +22,9 @@
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_CG
#include "Cg/cgD3D9.h"
#include <Cg/cgD3D9.h>
#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];

View File

@ -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 <CGparameter> _cg_parameter_map;
#endif
private:
void release_resources(void);
public:

View File

@ -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);
}
////////////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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 <CGparameter> _cg_parameter_map;
pvector<CGparameter> _cg_parameter_map;
CLP(GraphicsStateGuardian) *_glgsg;

View File

@ -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
}
////////////////////////////////////////////////////////////////////

View File

@ -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;

View File

@ -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)() {

View File

@ -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)();

View File

@ -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<CGparameter> &map) {
cg_compile_for(const ShaderCaps &caps, CGcontext context,
CGprogram &combined_program, pvector<CGparameter> &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<CGprogram> 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<n_mat; i++) {
// This is a bit awkward, we have to go in and seperate out the
// combined program, since all the parameter bindings have changed.
CGprogram programs_by_type[ST_COUNT];
for (int i = 0; i < cgGetNumProgramDomains(combined_program); ++i) {
// Conveniently, the CGdomain enum overlaps with ShaderType.
CGprogram program = cgGetProgramDomainProgram(combined_program, i);
programs_by_type[cgGetProgramDomain(program)] = program;
}
for (int i = 0; i < n_mat; ++i) {
const ShaderArgId &id = _mat_spec[i]._id;
CGprogram prog = cg_program_from_shadertype(id._type); // CG2 CHANGE
map[id._seqno] = cgGetNamedParameter(prog, id._name.c_str());
map[id._seqno] = cgGetNamedParameter(programs_by_type[id._type], id._name.c_str());
}
for (int i=0; i<n_tex; i++) {
for (int i = 0; i < n_tex; ++i) {
const ShaderArgId &id = _tex_spec[i]._id;
CGprogram prog = cg_program_from_shadertype(id._type); // CG2 CHANGE
map[id._seqno] = cgGetNamedParameter(prog, id._name.c_str());
if (cgGetParameterBaseResource(map[id._seqno]) == CG_UNDEFINED) {
map[id._seqno] = 0;
CGparameter p = cgGetNamedParameter(programs_by_type[id._type], id._name.c_str());
if (gobj_cat.is_debug()) {
const char *resource = cgGetParameterResourceName(p);
if (resource != NULL) {
gobj_cat.debug() << "Texture parameter " << id._name
<< " is bound to resource " << resource << "\n";
}
}
map[id._seqno] = p;
}
for (int i=0; i<n_var; i++) {
for (int i = 0; i < n_var; ++i) {
const ShaderArgId &id = _var_spec[i]._id;
CGparameter p = cgGetNamedParameter(programs_by_type[id._type], id._name.c_str());
CGprogram prog = cg_program_from_shadertype(id._type); // CG2 CHANGE
map[id._seqno] = cgGetNamedParameter(prog, id._name.c_str());
if (cgGetParameterBaseResource(map[id._seqno]) == CG_UNDEFINED) {
map[id._seqno] = 0;
const char *resource = cgGetParameterResourceName(p);
if (gobj_cat.is_debug() && resource != NULL) {
gobj_cat.debug()
<< "Varying parameter " << id._name << " is bound to resource "
<< cgGetParameterResourceName(p) << "\n";
}
}
for (int i=0; i<n_ptr; i++) {
const ShaderArgId &id = _ptr_spec[i]._id;
CGprogram prog = cg_program_from_shadertype(id._type); // CG2 CHANGE
map[id._seqno] = cgGetNamedParameter(prog, id._name.c_str());
if (cgGetParameterBaseResource(p) == CG_UNDEFINED) {
// I really don't know what this means, but it happens when I
// use the NORMAL0 semantic instead of NORMAL, or POSITION0
// instead of POSITION, etc. Not catching this results in a
// continuous stream of errors at the renderer side.
gobj_cat.error()
<< "Varying parameter " << id._name;
const char *semantic = cgGetParameterSemantic(p);
if (semantic != NULL) {
gobj_cat.error(false) << " : " << semantic;
}
if (resource != NULL) {
gobj_cat.error(false) << " (bound to resource " << resource << ")";
}
gobj_cat.error(false) << " is invalid!\n";
#ifndef NDEBUG
// Let's try to give the developer a hint...
if (semantic != NULL) {
if (strcmp(semantic, "POSITION0") == 0) {
gobj_cat.error() << "Try using the semantic POSITION instead of POSITION0.\n";
} else if (strcmp(semantic, "NORMAL0") == 0) {
gobj_cat.error() << "Try using the semantic NORMAL instead of NORMAL0.\n";
} else if (strcmp(semantic, "DIFFUSE0") == 0) {
gobj_cat.error() << "Try using the semantic DIFFUSE instead of DIFFUSE0.\n";
} else if (strcmp(semantic, "SPECULAR0") == 0) {
gobj_cat.error() << "Try using the semantic SPECULAR instead of SPECULAR0.\n";
} else if (strcmp(semantic, "FOGCOORD0") == 0) {
gobj_cat.error() << "Try using the semantic FOGCOORD instead of FOGCOORD0.\n";
} else if (strcmp(semantic, "PSIZE0") == 0) {
gobj_cat.error() << "Try using the semantic PSIZE instead of PSIZE0.\n";
}
}
#endif // NDEBUG
p = 0;
}
map[id._seqno] = p;
}
for (int i = 0; i < n_ptr; ++i) {
const ShaderArgId &id = _ptr_spec[i]._id;
map[id._seqno] = cgGetNamedParameter(programs_by_type[id._type], id._name.c_str());
}
// Transfer ownership of the compiled shader.
ctx = _cg_context;
vprogram = _cg_vprogram;
fprogram = _cg_fprogram;
gprogram = _cg_gprogram;
_cg_context = 0;
_cg_vprogram = 0;
_cg_fprogram = 0;
_cg_gprogram = 0;
if (_cg_vprogram != 0) {
cgDestroyProgram(_cg_vprogram);
_cg_vprogram = 0;
}
if (_cg_fprogram != 0) {
cgDestroyProgram(_cg_fprogram);
_cg_fprogram = 0;
}
if (_cg_gprogram != 0) {
cgDestroyProgram(_cg_gprogram);
_cg_gprogram = 0;
}
_cg_last_caps.clear();
@ -1921,7 +1990,6 @@ Shader(ShaderLanguage lang) :
_last_modified(0)
{
#ifdef HAVE_CG
_cg_context = 0;
_cg_vprogram = 0;
_cg_fprogram = 0;
_cg_gprogram = 0;
@ -2006,9 +2074,7 @@ read(const ShaderFile &sfile) {
// Determine which language the shader is written in.
if (_language == SL_Cg) {
#ifdef HAVE_CG
if (!_text._separate) {
cg_get_profile_from_header(_default_caps);
}
cg_get_profile_from_header(_default_caps);
if (!cg_analyze_shader(_default_caps)) {
gobj_cat.error()

View File

@ -63,6 +63,7 @@ PUBLISHED:
ST_tess_control,
ST_tess_evaluation,
ST_compute,
ST_COUNT
};
enum AutoShaderSwitch {
@ -472,12 +473,13 @@ private:
ShaderArgType cg_parameter_type(CGparameter p);
ShaderArgDir cg_parameter_dir(CGparameter p);
CGprogram cg_compile_entry_point(const char *entry, const ShaderCaps &caps, ShaderType type = ST_vertex);
CGprogram cg_compile_entry_point(const char *entry, const ShaderCaps &caps,
CGcontext context, ShaderType type);
bool cg_analyze_entry_point(CGprogram prog, ShaderType type);
bool cg_analyze_shader(const ShaderCaps &caps);
bool cg_compile_shader(const ShaderCaps &caps);
bool cg_compile_shader(const ShaderCaps &caps, CGcontext context);
void cg_release_resources();
void cg_report_errors();
@ -486,7 +488,7 @@ private:
void cg_get_profile_from_header(ShaderCaps &caps);
ShaderCaps _cg_last_caps;
CGcontext _cg_context;
static CGcontext _cg_context;
CGprogram _cg_vprogram;
CGprogram _cg_fprogram;
CGprogram _cg_gprogram;
@ -498,9 +500,8 @@ private:
CGprogram cg_program_from_shadertype(ShaderType type);
public:
bool cg_compile_for(const ShaderCaps &caps, CGcontext &ctx,
CGprogram &vprogram, CGprogram &fprogram,
CGprogram &gprogram, pvector<CGparameter> &map);
bool cg_compile_for(const ShaderCaps &caps, CGcontext context,
CGprogram &combined_program, pvector<CGparameter> &map);
#endif