merge shader_overhaul from jyelon

This commit is contained in:
David Rose 2007-03-15 21:04:31 +00:00
parent 2d8678de58
commit 1fdb425b88
22 changed files with 1843 additions and 1993 deletions

View File

@ -783,7 +783,7 @@ clear(DrawableRegion *clearable) {
//
////////////////////////////////////////////////////////////////////
const LMatrix4f *GraphicsStateGuardian::
fetch_specified_value(ShaderContext::ShaderMatSpec &spec, bool altered) {
fetch_specified_value(ShaderExpansion::ShaderMatSpec &spec, bool altered) {
static LMatrix4f acc;
const LMatrix4f *val1;
const LMatrix4f *val2;
@ -791,26 +791,26 @@ fetch_specified_value(ShaderContext::ShaderMatSpec &spec, bool altered) {
static LMatrix4f t2;
switch(spec._func) {
case ShaderContext::SMF_compose:
case ShaderExpansion::SMF_compose:
val1 = fetch_specified_part(spec._part[0], spec._arg[0], t1);
val2 = fetch_specified_part(spec._part[1], spec._arg[1], t2);
acc.multiply(*val1, *val2);
return &acc;
case ShaderContext::SMF_compose_cache_first:
case ShaderExpansion::SMF_compose_cache_first:
if (altered) {
spec._cache = *fetch_specified_part(spec._part[0], spec._arg[0], t1);
}
val2 = fetch_specified_part(spec._part[1], spec._arg[1], t2);
acc.multiply(spec._cache, *val2);
return &acc;
case ShaderContext::SMF_compose_cache_second:
case ShaderExpansion::SMF_compose_cache_second:
if (altered) {
spec._cache = *fetch_specified_part(spec._part[1], spec._arg[1], t2);
}
val1 = fetch_specified_part(spec._part[0], spec._arg[0], t1);
acc.multiply(*val1, spec._cache);
return &acc;
case ShaderContext::SMF_first:
case ShaderExpansion::SMF_first:
return fetch_specified_part(spec._part[0], spec._arg[0], t1);
default:
// should never get here
@ -824,24 +824,24 @@ fetch_specified_value(ShaderContext::ShaderMatSpec &spec, bool altered) {
// Description: See fetch_specified_value
////////////////////////////////////////////////////////////////////
const LMatrix4f *GraphicsStateGuardian::
fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMatrix4f &t) {
fetch_specified_part(ShaderExpansion::ShaderMatInput part, InternalName *name, LMatrix4f &t) {
switch(part) {
case ShaderContext::SMO_identity: {
case ShaderExpansion::SMO_identity: {
return &LMatrix4f::ident_mat();
}
case ShaderContext::SMO_window_size: {
case ShaderExpansion::SMO_window_size: {
t = LMatrix4f::translate_mat(_current_display_region->get_pixel_width(),
_current_display_region->get_pixel_height(),
0.0);
return &t;
}
case ShaderContext::SMO_pixel_size: {
case ShaderExpansion::SMO_pixel_size: {
t = LMatrix4f::translate_mat(_current_display_region->get_pixel_width(),
_current_display_region->get_pixel_height(),
0.0);
return &t;
}
case ShaderContext::SMO_card_center: {
case ShaderExpansion::SMO_card_center: {
int px = _current_display_region->get_pixel_width();
int py = _current_display_region->get_pixel_height();
t = LMatrix4f::translate_mat((px*0.5) / Texture::up_to_power_2(px),
@ -849,14 +849,14 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
0.0);
return &t;
}
case ShaderContext::SMO_mat_constant_x: {
case ShaderExpansion::SMO_mat_constant_x: {
const ShaderInput *input = _target._shader->get_shader_input(name);
if (input->get_nodepath().is_empty()) {
return &LMatrix4f::ident_mat();
}
return &(input->get_nodepath().node()->get_transform()->get_mat());
}
case ShaderContext::SMO_vec_constant_x: {
case ShaderExpansion::SMO_vec_constant_x: {
const ShaderInput *input = _target._shader->get_shader_input(name);
const float *data = input->get_vector().get_data();
t = LMatrix4f(data[0],data[1],data[2],data[3],
@ -865,28 +865,28 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
data[0],data[1],data[2],data[3]);
return &t;
}
case ShaderContext::SMO_world_to_view: {
case ShaderExpansion::SMO_world_to_view: {
return &(get_scene()->get_world_transform()->get_mat());
break;
}
case ShaderContext::SMO_view_to_world: {
case ShaderExpansion::SMO_view_to_world: {
return &(get_scene()->get_camera_transform()->get_mat());
}
case ShaderContext::SMO_model_to_view: {
case ShaderExpansion::SMO_model_to_view: {
return &(get_external_transform()->get_mat());
}
case ShaderContext::SMO_view_to_model: {
case ShaderExpansion::SMO_view_to_model: {
// DANGER: SLOW AND NOT CACHEABLE!
t.invert_from(get_external_transform()->get_mat());
return &t;
}
case ShaderContext::SMO_apiview_to_view: {
case ShaderExpansion::SMO_apiview_to_view: {
return &(_inv_cs_transform->get_mat());
}
case ShaderContext::SMO_view_to_apiview: {
case ShaderExpansion::SMO_view_to_apiview: {
return &(_cs_transform->get_mat());
}
case ShaderContext::SMO_clip_to_view: {
case ShaderExpansion::SMO_clip_to_view: {
if (_current_lens->get_coordinate_system() == _coordinate_system) {
return &(_current_lens->get_projection_mat_inv(_current_stereo_channel));
} else {
@ -895,7 +895,7 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
return &t;
}
}
case ShaderContext::SMO_view_to_clip: {
case ShaderExpansion::SMO_view_to_clip: {
if (_current_lens->get_coordinate_system() == _coordinate_system) {
return &(_current_lens->get_projection_mat(_current_stereo_channel));
} else {
@ -904,15 +904,15 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
return &t;
}
}
case ShaderContext::SMO_apiclip_to_view: {
case ShaderExpansion::SMO_apiclip_to_view: {
t = _projection_mat_inv->get_mat() * _inv_cs_transform->get_mat();
return &t;
}
case ShaderContext::SMO_view_to_apiclip: {
case ShaderExpansion::SMO_view_to_apiclip: {
t = _cs_transform->get_mat() * _projection_mat->get_mat();
return &t;
}
case ShaderContext::SMO_view_x_to_view: {
case ShaderExpansion::SMO_view_x_to_view: {
const ShaderInput *input = _target._shader->get_shader_input(name);
if (input->get_nodepath().is_empty()) {
@ -927,7 +927,7 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
get_scene()->get_world_transform()->get_mat();
return &t;
}
case ShaderContext::SMO_view_to_view_x: {
case ShaderExpansion::SMO_view_to_view_x: {
const ShaderInput *input = _target._shader->get_shader_input(name);
if (input->get_nodepath().is_empty()) {
@ -942,7 +942,7 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
invert(input->get_nodepath().get_net_transform()->get_mat());
return &t;
}
case ShaderContext::SMO_apiview_x_to_view: {
case ShaderExpansion::SMO_apiview_x_to_view: {
const ShaderInput *input = _target._shader->get_shader_input(name);
nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat());
t = LMatrix4f::convert_mat(_internal_coordinate_system, _coordinate_system) *
@ -950,7 +950,7 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
get_scene()->get_world_transform()->get_mat();
return &t;
}
case ShaderContext::SMO_view_to_apiview_x: {
case ShaderExpansion::SMO_view_to_apiview_x: {
const ShaderInput *input = _target._shader->get_shader_input(name);
nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat());
t = (get_scene()->get_camera_transform()->get_mat() *
@ -958,7 +958,7 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
LMatrix4f::convert_mat(_coordinate_system, _internal_coordinate_system));
return &t;
}
case ShaderContext::SMO_clip_x_to_view: {
case ShaderExpansion::SMO_clip_x_to_view: {
const ShaderInput *input = _target._shader->get_shader_input(name);
nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat());
Lens *lens = DCAST(LensNode, input->get_nodepath().node())->get_lens();
@ -968,7 +968,7 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
get_scene()->get_world_transform()->get_mat();
return &t;
}
case ShaderContext::SMO_view_to_clip_x: {
case ShaderExpansion::SMO_view_to_clip_x: {
const ShaderInput *input = _target._shader->get_shader_input(name);
nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat());
Lens *lens = DCAST(LensNode, input->get_nodepath().node())->get_lens();
@ -978,11 +978,11 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
lens->get_projection_mat(_current_stereo_channel);
return &t;
}
case ShaderContext::SMO_apiclip_x_to_view: {
case ShaderExpansion::SMO_apiclip_x_to_view: {
// NOT IMPLEMENTED
return &LMatrix4f::ident_mat();
}
case ShaderContext::SMO_view_to_apiclip_x: {
case ShaderExpansion::SMO_view_to_apiclip_x: {
// NOT IMPLEMENTED
return &LMatrix4f::ident_mat();
}

View File

@ -194,8 +194,8 @@ public:
void clear(DrawableRegion *clearable);
const LMatrix4f *fetch_specified_value(ShaderContext::ShaderMatSpec &spec, bool altered);
const LMatrix4f *fetch_specified_part(ShaderContext::ShaderMatInput input, InternalName *name, LMatrix4f &t);
const LMatrix4f *fetch_specified_value(ShaderExpansion::ShaderMatSpec &spec, bool altered);
const LMatrix4f *fetch_specified_part(ShaderExpansion::ShaderMatInput input, InternalName *name, LMatrix4f &t);
virtual void prepare_display_region(DisplayRegionPipelineReader *dr,
Lens::StereoChannel stereo_channel);
@ -410,6 +410,8 @@ protected:
static PT(TextureStage) _alpha_scale_texture_stage;
ShaderExpansion::ShaderCaps _shader_caps;
public:
// Statistics
static PStatCollector _vertex_buffer_switch_pcollector;

View File

@ -61,6 +61,9 @@
#include "pStatTimer.h"
#include "pStatCollector.h"
#include "wdxGraphicsBuffer9.h"
#ifdef HAVE_CG
#include "Cg/cgD3D9.h"
#endif
#include <mmsystem.h>
@ -147,10 +150,6 @@ DXGraphicsStateGuardian9(GraphicsPipe *pipe) :
_vertex_shader_maximum_constants = 0;
_supports_stream_offset = false;
#ifdef HAVE_CGDX9
_cg_context = 0;
#endif
}
////////////////////////////////////////////////////////////////////
@ -169,14 +168,6 @@ DXGraphicsStateGuardian9::
delete _lru;
_lru = 0;
}
#ifdef HAVE_CGDX9
if (_cg_context) {
cgD3D9SetDevice (NULL);
cgDestroyContext (_cg_context);
_cg_context = 0;
}
#endif
}
////////////////////////////////////////////////////////////////////
@ -346,10 +337,9 @@ release_texture(TextureContext *tc) {
////////////////////////////////////////////////////////////////////
ShaderContext *CLP(GraphicsStateGuardian)::
prepare_shader(ShaderExpansion *se) {
#ifdef HAVE_CGDX9
#ifdef HAVE_CG
CLP(ShaderContext) *result = new CLP(ShaderContext)(se, this);
if (this -> _cg_context) return result;
delete result;
return result;
#endif
return NULL;
}
@ -2395,7 +2385,6 @@ reset() {
_vertex_shader_maximum_constants = d3d_caps.MaxVertexShaderConst;
#ifdef HAVE_CGDX9
switch (_pixel_shader_version_major)
{
case 0:
@ -2419,11 +2408,49 @@ reset() {
_shader_model = SM_40;
break;
}
#else
_shader_model = SM_00;
#endif
_auto_detect_shader_model = _shader_model;
#ifdef HAVE_CG
cgD3D9SetDevice (_d3d_device);
if (cgD3D9IsProfileSupported(CG_PROFILE_PS_2_0) &&
cgD3D9IsProfileSupported(CG_PROFILE_VS_2_0)) {
_supports_basic_shaders = true;
_shader_caps._active_vprofile = (int)cgD3D9GetLatestVertexProfile();
_shader_caps._active_fprofile = (int)cgD3D9GetLatestPixelProfile();
_shader_caps._ultimate_vprofile = (int)CG_PROFILE_VS_3_0;
_shader_caps._ultimate_fprofile = (int)CG_PROFILE_PS_3_0;
}
if (dxgsg9_cat.is_debug()) {
CGprofile vertex_profile;
CGprofile pixel_profile;
vertex_profile = cgD3D9GetLatestVertexProfile( );
pixel_profile = cgD3D9GetLatestPixelProfile( );
const char *vertex_profile_str =
cgGetProfileString(vertex_profile);
const char *pixel_profile_str =
cgGetProfileString(pixel_profile);
if (vertex_profile_str == NULL) {
vertex_profile_str = "(null)";
}
if (pixel_profile_str == NULL) {
pixel_profile_str = "(null)";
}
dxgsg9_cat.debug()
<< "\nCg vertex profile = " << vertex_profile_str << " id = " << vertex_profile
<< "\nCg pixel profile = " << pixel_profile_str << " id = " << pixel_profile
<< "\nshader model = " << _shader_model
<< "\n";
}
#endif
_supports_stream_offset = (d3d_caps.DevCaps2 & D3DDEVCAPS2_STREAMOFFSET) != 0;
_screen->_supports_dynamic_textures = ((d3d_caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) != 0);
_screen->_supports_automatic_mipmap_generation = ((d3d_caps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) != 0);
@ -2475,52 +2502,6 @@ reset() {
this -> reset_render_states ( );
// duplicates OpenGL version (ARB_vertex_program extension and
// ARB_fragment_program extension)
if (_vertex_shader_version_major >= 1 &&
_pixel_shader_version_major >= 2) {
_supports_basic_shaders = true;
}
#ifdef HAVE_CGDX9
if (_cg_context == 0) {
_cg_context = cgCreateContext ( );
cgD3D9SetDevice (_d3d_device);
}
else {
cgD3D9SetDevice (_d3d_device);
}
if (_cg_context) {
if (dxgsg9_cat.is_debug()) {
CGprofile vertex_profile;
CGprofile pixel_profile;
vertex_profile = cgD3D9GetLatestVertexProfile( );
pixel_profile = cgD3D9GetLatestPixelProfile( );
const char *vertex_profile_str =
cgGetProfileString(vertex_profile);
const char *pixel_profile_str =
cgGetProfileString(pixel_profile);
if (vertex_profile_str == NULL) {
vertex_profile_str = "(null)";
}
if (pixel_profile_str == NULL) {
pixel_profile_str = "(null)";
}
dxgsg9_cat.debug()
<< "\nCg vertex profile = " << vertex_profile_str << " id = " << vertex_profile
<< "\nCg pixel profile = " << pixel_profile_str << " id = " << pixel_profile
<< "\nshader model = " << _shader_model
<< "\n";
}
}
#endif
_max_vertices_per_array = d3d_caps.MaxVertexIndex;
_max_vertices_per_primitive = d3d_caps.MaxPrimitiveCount;
@ -2945,7 +2926,7 @@ do_issue_shader() {
ShaderExpansion *expansion = _target_rs->get_shader_expansion();
if (expansion == 0) {
if (_target._shader->get_shader() != 0) {
expansion = _target._shader->get_shader()->macroexpand(_target_rs);
expansion = _target._shader->get_shader()->macroexpand(_target_rs, _shader_caps);
// I am casting away the const-ness of this pointer, because
// the 'shader-expansion' field is just a cache.
((RenderState *)((const RenderState*)_target_rs))->

View File

@ -250,11 +250,7 @@ protected:
public:
DXScreenData *_screen;
#ifdef HAVE_CGDX9
CGcontext _cg_context;
#endif
protected:
LPDIRECT3DDEVICE9 _d3d_device; // same as _screen->_d3d_device, cached for spd
IDirect3DSwapChain9 *_swap_chain;

View File

@ -27,6 +27,11 @@
////////////////////////////////////////////////////////////////////
INLINE bool CLP(ShaderContext)::
valid (GSG *gsg) {
return _state;
#ifdef HAVE_CG
if (_cg_context) {
return true;
}
#endif
return false;
}

View File

@ -25,54 +25,14 @@
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_CG
#include "Cg/cgD3D9.h"
#endif
#define DEBUG_SHADER 0
TypeHandle CLP(ShaderContext)::_type_handle;
static char *vertex_shader_function_name = "vshader";
static char *pixel_shader_function_name = "fshader";
#ifdef HAVE_CGDX9
////////////////////////////////////////////////////////////////////
// Function: cg_type_to_panda_type
// Access: Public, Static
// Description: convert a cg shader-arg type to a panda shader-arg type.
////////////////////////////////////////////////////////////////////
static ShaderContext::ShaderArgType
cg_type_to_panda_type(CGtype n) {
switch (n) {
case CG_FLOAT1: return ShaderContext::SAT_float1;
case CG_FLOAT2: return ShaderContext::SAT_float2;
case CG_FLOAT3: return ShaderContext::SAT_float3;
case CG_FLOAT4: return ShaderContext::SAT_float4;
case CG_FLOAT4x4: return ShaderContext::SAT_float4x4;
case CG_SAMPLER1D: return ShaderContext::SAT_sampler1d;
case CG_SAMPLER2D: return ShaderContext::SAT_sampler2d;
case CG_SAMPLER3D: return ShaderContext::SAT_sampler3d;
case CG_SAMPLERCUBE: return ShaderContext::SAT_samplercube;
default: return ShaderContext::SAT_unknown;
}
}
#endif // HAVE_CGDX9
#ifdef HAVE_CGDX9
////////////////////////////////////////////////////////////////////
// Function: cg_dir_to_panda_dir
// Access: Public, Static
// Description: convert a cg shader-arg type to a panda shader-arg type.
////////////////////////////////////////////////////////////////////
static ShaderContext::ShaderArgDir
cg_dir_to_panda_dir(CGenum n) {
switch (n) {
case CG_IN: return ShaderContext::SAD_in;
case CG_OUT: return ShaderContext::SAD_out;
case CG_INOUT: return ShaderContext::SAD_inout;
default: return ShaderContext::SAD_unknown;
}
}
#endif // HAVE_CGDX9
////////////////////////////////////////////////////////////////////
// Function: DXShaderContext9::Constructor
// Access: Public
@ -80,80 +40,70 @@ cg_dir_to_panda_dir(CGenum n) {
////////////////////////////////////////////////////////////////////
CLP(ShaderContext)::
CLP(ShaderContext)(ShaderExpansion *s, GSG *gsg) : ShaderContext(s) {
string header;
s->parse_init();
s->parse_line(header, true, true);
_state = false;
#ifdef HAVE_CGDX9
DBG_SH2 dxgsg9_cat.debug ( ) << "SHADER: Create ShaderContext \n"; DBG_E
_cg_shader = false;
_cg_profile[SHADER_type_vert] = CG_PROFILE_UNKNOWN;
_cg_profile[SHADER_type_frag] = CG_PROFILE_UNKNOWN;
_cg_program[SHADER_type_vert] = (CGprogram)0;
_cg_program[SHADER_type_frag] = (CGprogram)0;
_vertex_size = 0;
_vertex_element_array = 0;
_total_dx_parameters = 0;
_dx_parameter_array = 0;
_transpose_matrix = false;
_name = s->get_name ( );
if (header == "//Cg") {
#ifdef HAVE_CG
if (s->get_header() == "//Cg") {
// Ask the shader expansion to compile itself for us and
// to give us the resulting Cg program objects.
// CGcontext is created once during Reset ( )
if (gsg -> _cg_context == 0) {
release_resources();
dxgsg9_cat.error() << "Cg not supported by this video card.\n";
if (!s->cg_compile_for(gsg->_shader_caps,
_cg_context,
_cg_vprogram,
_cg_fprogram,
_cg_parameter_map)) {
return;
}
// Load the program.
// Parse any directives in the source.
// IGNORE SPECIFIC PROFILES IN DX FOR NOW
if (false) {
string directive;
while (!s->parse_eof()) {
s->parse_line(directive, true, true);
vector_string pieces;
tokenize(directive, pieces, " \t");
if ((pieces.size()==4)&&(pieces[0]=="//Cg")&&(pieces[1]=="profile")) {
suggest_cg_profile(pieces[2], pieces[3]);
}
}
}
// Select a profile if no preferred profile specified in the source.
if (_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN) {
_cg_profile[SHADER_type_vert] = cgD3D9GetLatestVertexProfile( );
}
if (_cg_profile[SHADER_type_frag] == CG_PROFILE_UNKNOWN) {
_cg_profile[SHADER_type_frag] = cgD3D9GetLatestPixelProfile( );
}
// If we still haven't chosen a profile, give up.
if ((_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN)||
(_cg_profile[SHADER_type_frag] == CG_PROFILE_UNKNOWN)) {
release_resources();
dxgsg9_cat.error() << "Cg not supported by this video card.\n";
return;
}
// Compile the program.
_cg_shader = true;
try_cg_compile(s, gsg);
return;
}
BOOL paramater_shadowing;
DWORD assembly_flags;
paramater_shadowing = FALSE;
assembly_flags = 0;
#if DEBUG_SHADER
assembly_flags |= D3DXSHADER_DEBUG;
#endif
dxgsg9_cat.error() << s->get_name() << ": unrecognized shader language " << header << "\n";
HRESULT hr;
bool success = true;
hr = cgD3D9LoadProgram(_cg_vprogram, paramater_shadowing, assembly_flags);
if (FAILED (hr)) {
dxgsg9_cat.error()
<< "vertex shader 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;
}
if (!success) {
release_resources();
}
}
#endif
}
////////////////////////////////////////////////////////////////////
@ -171,340 +121,53 @@ CLP(ShaderContext)::
}
}
#ifdef HAVE_CGDX9
////////////////////////////////////////////////////////////////////
// Function: Shader::report_cg_compile_errors
// Access: Public, Static
// Description: Used only after a Cg compile command, to print
// out any error messages that may have occurred
// during the Cg shader compilation. The 'file'
// is the name of the file containing the Cg code.
////////////////////////////////////////////////////////////////////
void CLP(ShaderContext)::
report_cg_compile_errors(const string &file, CGcontext ctx)
{
CGerror err = cgGetError();
if (err != CG_NO_ERROR) {
if (err == CG_COMPILER_ERROR) {
string listing = cgGetLastListing(ctx);
vector_string errlines;
tokenize(listing, errlines, "\n");
for (int i=0; i<(int)errlines.size(); i++) {
string line = trim(errlines[i]);
if (line != "") {
dxgsg9_cat.error() << file << " " << errlines[i] << "\n";
}
}
} else {
dxgsg9_cat.error() << file << ": " << cgGetErrorString(err) << "\n";
}
}
}
#endif // HAVE_CGDX9
////////////////////////////////////////////////////////////////////
// Function: DXShaderContext9::suggest_cg_profile
// Access: Private
// Description: xyz
////////////////////////////////////////////////////////////////////
#ifdef HAVE_CGDX9
void CLP(ShaderContext)::
suggest_cg_profile(const string &vpro, const string &fpro)
{
// If a good profile has already been suggested, ignore suggestion.
if ((_cg_profile[SHADER_type_vert] != CG_PROFILE_UNKNOWN)||
(_cg_profile[SHADER_type_frag] != CG_PROFILE_UNKNOWN)) {
return;
}
// Parse the suggestion. If not parseable, print error and ignore.
_cg_profile[SHADER_type_vert] = parse_cg_profile(vpro, true);
_cg_profile[SHADER_type_frag] = parse_cg_profile(fpro, false);
if ((_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN)||
(_cg_profile[SHADER_type_frag] == CG_PROFILE_UNKNOWN)) {
dxgsg9_cat.error() << "Cg: unrecognized profile name: " << vpro << " " << fpro << "\n";
_cg_profile[SHADER_type_vert] = CG_PROFILE_UNKNOWN;
_cg_profile[SHADER_type_frag] = CG_PROFILE_UNKNOWN;
return;
}
// NO EQUIVALENT FUNCTIONALITY FROM GL TO DX
/*
// If the suggestion is parseable, but not supported, ignore silently.
if ((!cgGLIsProfileSupported(_cg_profile[SHADER_type_vert]))||
(!cgGLIsProfileSupported(_cg_profile[SHADER_type_frag]))) {
_cg_profile[SHADER_type_vert] = CG_PROFILE_UNKNOWN;
_cg_profile[SHADER_type_frag] = CG_PROFILE_UNKNOWN;
return;
}
*/
}
#endif
////////////////////////////////////////////////////////////////////
// Function: DXShaderContext9::parse_cg_profile
// Access: Private
// Description: xyz
////////////////////////////////////////////////////////////////////
#ifdef HAVE_CGDX9
CGprofile CLP(ShaderContext)::
parse_cg_profile(const string &id, bool vertex)
{
int i = 0;
CGprofile vprofiles[] = { CG_PROFILE_ARBVP1, CG_PROFILE_VP20, CG_PROFILE_VP30, CG_PROFILE_VP40, CG_PROFILE_UNKNOWN };
CGprofile fprofiles[] = { CG_PROFILE_ARBFP1, CG_PROFILE_FP20, CG_PROFILE_FP30, CG_PROFILE_FP40, CG_PROFILE_UNKNOWN };
// near equivalent DX profiles
#if (CG_VERSION_NUM >= 1502)
CGprofile dx_vprofiles[] = { CG_PROFILE_VS_2_0, CG_PROFILE_VS_1_1, CG_PROFILE_VS_2_X, CG_PROFILE_VS_3_0, CG_PROFILE_UNKNOWN };
CGprofile dx_fprofiles[] = { CG_PROFILE_PS_2_0, CG_PROFILE_PS_1_1, CG_PROFILE_PS_2_X, CG_PROFILE_PS_3_0, CG_PROFILE_UNKNOWN };
#else
CGprofile dx_vprofiles[] = { CG_PROFILE_VS_2_0, CG_PROFILE_VS_1_1, CG_PROFILE_VS_2_X, CG_PROFILE_VS_2_X, CG_PROFILE_UNKNOWN };
CGprofile dx_fprofiles[] = { CG_PROFILE_PS_2_0, CG_PROFILE_PS_1_1, CG_PROFILE_PS_2_X, CG_PROFILE_PS_2_X, CG_PROFILE_UNKNOWN };
#endif
if (vertex) {
while (vprofiles[i] != CG_PROFILE_UNKNOWN) {
if (id == cgGetProfileString(vprofiles[i])) {
return dx_vprofiles[i];
}
i++;
}
} else {
while (fprofiles[i] != CG_PROFILE_UNKNOWN) {
if (id == cgGetProfileString(fprofiles[i])) {
return dx_fprofiles[i];
}
i++;
}
}
return CG_PROFILE_UNKNOWN;
}
#endif // HAVE_CGDX9
int save_file (int size, void *data, char *file_path)
{
int state;
int file_handle;
state = false;
file_handle = _open (file_path, _O_CREAT | _O_RDWR | _O_TRUNC, _S_IREAD | _S_IWRITE);
if (file_handle != -1) {
if (_write (file_handle, data, size) == size) {
state = true;
}
_close (file_handle);
}
return state;
}
////////////////////////////////////////////////////////////////////
// Function: DXShaderContext9::try_cg_compile
// Access: Private
// Description: xyz
////////////////////////////////////////////////////////////////////
#ifdef HAVE_CGDX9
bool CLP(ShaderContext)::
try_cg_compile(ShaderExpansion *s, GSG *gsg)
{
cgGetError();
_cg_program[0] =
cgCreateProgram(gsg -> _cg_context, CG_SOURCE, s->_text.c_str(),
_cg_profile[0], vertex_shader_function_name, (const char**)NULL);
report_cg_compile_errors(s->get_name(), gsg -> _cg_context);
cgGetError();
_cg_program[1] =
cgCreateProgram(gsg -> _cg_context, CG_SOURCE, s->_text.c_str(),
_cg_profile[1], pixel_shader_function_name, (const char**)NULL);
report_cg_compile_errors(s->get_name(), gsg -> _cg_context);
if ((_cg_program[SHADER_type_vert]==0)||(_cg_program[SHADER_type_frag]==0)) {
release_resources();
return false;
}
if (dxgsg9_cat.is_debug()) {
// DEBUG: output the generated program
const char *vertex_program;
const char *pixel_program;
vertex_program = cgGetProgramString (_cg_program[0], CG_COMPILED_PROGRAM);
pixel_program = cgGetProgramString (_cg_program[1], CG_COMPILED_PROGRAM);
dxgsg9_cat.debug() << vertex_program << "\n";
dxgsg9_cat.debug() << pixel_program << "\n";
// save the generated program to a file
int size;
char file_path [512];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
_splitpath (_name.c_str ( ), drive, dir, fname, ext);
size = strlen (vertex_program);
sprintf (file_path, "%s.vasm", fname);
save_file (size, (void *) vertex_program, file_path);
size = strlen (pixel_program);
sprintf (file_path, "%s.pasm", fname);
save_file (size, (void *) pixel_program, file_path);
}
// The following code is present to work around a bug in the Cg compiler.
// It does not generate correct code for shadow map lookups when using arbfp1.
// This is a particularly onerous limitation, given that arbfp1 is the only
// Cg target that works on radeons. I suspect this is an intentional
// omission on nvidia's part. The following code fetches the output listing,
// detects the error, repairs the code, and resumbits the repaired code to Cg.
if ((_cg_profile[1] == CG_PROFILE_ARBFP1) && (gsg->_supports_shadow_filter)) {
bool shadowunit[32];
bool anyshadow = false;
memset(shadowunit, 0, sizeof(shadowunit));
vector_string lines;
tokenize(cgGetProgramString(_cg_program[1], CG_COMPILED_PROGRAM), lines, "\n");
// figure out which texture units contain shadow maps.
for (int lineno=0; lineno<(int)lines.size(); lineno++) {
if (lines[lineno].compare(0,21,"#var sampler2DSHADOW ")) {
continue;
}
vector_string fields;
tokenize(lines[lineno], fields, ":");
if (fields.size()!=5) {
continue;
}
vector_string words;
tokenize(trim(fields[2]), words, " ");
if (words.size()!=2) {
continue;
}
int unit = atoi(words[1].c_str());
if ((unit < 0)||(unit >= 32)) {
continue;
}
anyshadow = true;
shadowunit[unit] = true;
}
// modify all TEX statements that use the relevant texture units.
if (anyshadow) {
for (int lineno=0; lineno<(int)lines.size(); lineno++) {
if (lines[lineno].compare(0,4,"TEX ")) {
continue;
}
vector_string fields;
tokenize(lines[lineno], fields, ",");
if ((fields.size()!=4)||(trim(fields[3]) != "2D;")) {
continue;
}
vector_string texunitf;
tokenize(trim(fields[2]), texunitf, "[]");
if ((texunitf.size()!=3)||(texunitf[0] != "texture")||(texunitf[2]!="")) {
continue;
}
int unit = atoi(texunitf[1].c_str());
if ((unit < 0) || (unit >= 32) || (shadowunit[unit]==false)) {
continue;
}
lines[lineno] = fields[0]+","+fields[1]+","+fields[2]+", SHADOW2D;";
}
string result = "!!ARBfp1.0\nOPTION ARB_fragment_program_shadow;\n";
for (int lineno=1; lineno<(int)lines.size(); lineno++) {
result += (lines[lineno] + "\n");
}
cgDestroyProgram(_cg_program[1]);
_cg_program[1] =
cgCreateProgram(gsg -> _cg_context, CG_OBJECT, result.c_str(),
_cg_profile[1], "fshader", (const char**)NULL);
report_cg_compile_errors(s->get_name(), gsg -> _cg_context);
if (_cg_program[SHADER_type_frag]==0) {
release_resources();
return false;
}
}
}
bool success = true;
CGparameter parameter;
for (int progindex=0; progindex<2; progindex++) {
int nvtx = _var_spec.size();
for (parameter = cgGetFirstLeafParameter(_cg_program[progindex],CG_PROGRAM);
parameter != 0;
parameter = cgGetNextLeafParameter(parameter)) {
CGenum vbl = cgGetParameterVariability(parameter);
if ((vbl==CG_VARYING)||(vbl==CG_UNIFORM)) {
success &= compile_parameter(parameter,
cgGetParameterName(parameter),
cg_type_to_panda_type(cgGetParameterType(parameter)),
cg_dir_to_panda_dir(cgGetParameterDirection(parameter)),
(vbl == CG_VARYING),
dxgsg9_cat.get_safe_ptr());
}
}
if ((progindex == SHADER_type_frag) && (nvtx != _var_spec.size())) {
dxgsg9_cat.error() << "Cannot use vtx parameters in an fshader\n";
success = false;
}
}
if (!success) {
release_resources();
return false;
}
BOOL paramater_shadowing;
DWORD assembly_flags;
paramater_shadowing = FALSE;
assembly_flags = 0;
#if DEBUG_SHADER
assembly_flags |= D3DXSHADER_DEBUG;
#endif
HRESULT hr;
hr = cgD3D9LoadProgram(_cg_program[SHADER_type_vert], paramater_shadowing, assembly_flags);
if (FAILED (hr)) {
dxgsg9_cat.error()
<< "vertex shader cgD3D9LoadProgram failed "
<< D3DERRORSTRING(hr);
CGerror error = cgGetError();
if (error != CG_NO_ERROR) {
dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n";
}
release_resources();
return false;
}
hr = cgD3D9LoadProgram(_cg_program[SHADER_type_frag], 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";
}
release_resources();
return false;
}
DBG_SH2 dxgsg9_cat.debug ( ) << "SHADER: end try_cg_compile \n"; DBG_E
_state = true;
return true;
}
#endif
// int save_file (int size, void *data, char *file_path)
// {
// int state;
// int file_handle;
//
// state = false;
// file_handle = _open (file_path, _O_CREAT | _O_RDWR | _O_TRUNC, _S_IREAD | _S_IWRITE);
// if (file_handle != -1) {
// if (_write (file_handle, data, size) == size) {
// state = true;
// }
// _close (file_handle);
// }
//
// return state;
// }
//
// if (dxgsg9_cat.is_debug()) {
// // DEBUG: output the generated program
// const char *vertex_program;
// const char *pixel_program;
//
// vertex_program = cgGetProgramString (_cg_program[0], CG_COMPILED_PROGRAM);
// pixel_program = cgGetProgramString (_cg_program[1], CG_COMPILED_PROGRAM);
//
// dxgsg9_cat.debug() << vertex_program << "\n";
// dxgsg9_cat.debug() << pixel_program << "\n";
//
// // save the generated program to a file
// int size;
// char file_path [512];
//
// char drive[_MAX_DRIVE];
// char dir[_MAX_DIR];
// char fname[_MAX_FNAME];
// char ext[_MAX_EXT];
//
// _splitpath (_name.c_str ( ), drive, dir, fname, ext);
//
// size = strlen (vertex_program);
// sprintf (file_path, "%s.vasm", fname);
// save_file (size, (void *) vertex_program, file_path);
//
// size = strlen (pixel_program);
// sprintf (file_path, "%s.pasm", fname);
// save_file (size, (void *) pixel_program, file_path);
// }
////////////////////////////////////////////////////////////////////
// Function: DXShaderContext9::release_resources
@ -514,12 +177,13 @@ try_cg_compile(ShaderExpansion *s, GSG *gsg)
////////////////////////////////////////////////////////////////////
void CLP(ShaderContext)::
release_resources() {
#ifdef HAVE_CGDX9
{
_cg_profile[SHADER_type_vert] = (CGprofile)0;
_cg_profile[SHADER_type_frag] = (CGprofile)0;
_cg_program[SHADER_type_vert] = (CGprogram)0;
_cg_program[SHADER_type_frag] = (CGprogram)0;
#ifdef HAVE_CG
if (_cg_context) {
cgDestroyContext(_cg_context);
_cg_context = 0;
_cg_vprogram = 0;
_cg_fprogram = 0;
_cg_parameter_map.clear();
}
#endif
}
@ -537,45 +201,42 @@ bind(GSG *gsg) {
bool bind_state;
bind_state = false;
#ifdef HAVE_CGDX9
if (_state) {
if (gsg -> _cg_context != 0) {
DBG_SH5 dxgsg9_cat.debug ( ) << "SHADER: bind \n"; DBG_E
#ifdef HAVE_CG
if (_cg_context) {
DBG_SH5 dxgsg9_cat.debug ( ) << "SHADER: bind \n"; DBG_E
// clear the last cached FVF to make sure the next SetFVF call goes through
gsg -> _last_fvf = 0;
// clear the last cached FVF to make sure the next SetFVF call goes through
gsg -> _last_fvf = 0;
// Pass in k-parameters and transform-parameters
issue_parameters(gsg, true);
HRESULT hr;
if (_cg_shader) {
// Bind the shaders.
bind_state = true;
hr = cgD3D9BindProgram(_cg_program[SHADER_type_vert]);
if (FAILED (hr)) {
dxgsg9_cat.error() << "cgD3D9BindProgram vertex shader failed " << D3DERRORSTRING(hr);
CGerror error = cgGetError();
if (error != CG_NO_ERROR) {
dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n";
}
bind_state = false;
}
hr = cgD3D9BindProgram(_cg_program[SHADER_type_frag]);
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;
}
// Pass in k-parameters and transform-parameters
issue_parameters(gsg, true);
HRESULT hr;
// Bind the shaders.
bind_state = true;
hr = cgD3D9BindProgram(_cg_vprogram);
if (FAILED (hr)) {
dxgsg9_cat.error() << "cgD3D9BindProgram vertex shader failed " << D3DERRORSTRING(hr);
CGerror error = cgGetError();
if (error != CG_NO_ERROR) {
dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n";
}
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;
}
}
#endif
@ -591,8 +252,8 @@ bind(GSG *gsg) {
void CLP(ShaderContext)::
unbind(GSG *gsg) {
#ifdef HAVE_CGDX9
if (_state) {
#ifdef HAVE_CG
if (_cg_context) {
DBG_SH5 dxgsg9_cat.debug ( ) << "SHADER: unbind \n"; DBG_E
@ -638,12 +299,12 @@ InternalName *global_internal_name_1 = 0;
void CLP(ShaderContext)::
issue_parameters(GSG *gsg, bool altered)
{
#ifdef HAVE_CGDX9
if (gsg -> _cg_context != 0) {
for (int i=0; i<(int)_mat_spec.size(); i++) {
if (altered || _mat_spec[i]._trans_dependent) {
CGparameter p = (CGparameter)(_mat_spec[i]._parameter);
const LMatrix4f *val = gsg->fetch_specified_value(_mat_spec[i], altered);
#ifdef HAVE_CG
if (_cg_context) {
for (int i=0; i<(int)_expansion->_mat_spec.size(); i++) {
if (altered || _expansion->_mat_spec[i]._trans_dependent) {
CGparameter p = _cg_parameter_map[_expansion->_mat_spec[i]._id._seqno];
const LMatrix4f *val = gsg->fetch_specified_value(_expansion->_mat_spec[i], altered);
if (val) {
HRESULT hr;
float v [4];
@ -658,13 +319,13 @@ issue_parameters(GSG *gsg, bool altered)
#if DEBUG_SHADER
// DEBUG
global_data = (float *) data;
global_shader_mat_spec = &_mat_spec[i];
global_shader_mat_spec = &_expansion->_mat_spec[i];
global_internal_name_0 = global_shader_mat_spec -> _arg [0];
global_internal_name_1 = global_shader_mat_spec -> _arg [1];
#endif
switch (_mat_spec[i]._piece) {
case SMP_whole:
switch (_expansion->_mat_spec[i]._piece) {
case ShaderExpansion::SMP_whole:
// TRANSPOSE REQUIRED
temp_matrix.transpose_from (*val);
data = temp_matrix.get_data();
@ -672,7 +333,7 @@ issue_parameters(GSG *gsg, bool altered)
hr = cgD3D9SetUniform (p, data);
DBG_SH2
dxgsg9_cat.debug ( ) << "SMP_whole MATRIX \n" <<
dxgsg9_cat.debug ( ) << "ShaderExpansion::SMP_whole MATRIX \n" <<
data[ 0] << " " << data[ 1] << " " << data[ 2] << " " << data[ 3] << "\n" <<
data[ 4] << " " << data[ 5] << " " << data[ 6] << " " << data[ 7] << "\n" <<
data[ 8] << " " << data[ 9] << " " << data[10] << " " << data[11] << "\n" <<
@ -681,44 +342,44 @@ issue_parameters(GSG *gsg, bool altered)
break;
case SMP_transpose:
case ShaderExpansion::SMP_transpose:
// NO TRANSPOSE REQUIRED
hr = cgD3D9SetUniform (p, data);
break;
case SMP_row0:
case ShaderExpansion::SMP_row0:
hr = cgD3D9SetUniform (p, data + 0);
break;
case SMP_row1:
case ShaderExpansion::SMP_row1:
hr = cgD3D9SetUniform (p, data + 4);
break;
case SMP_row2:
case ShaderExpansion::SMP_row2:
hr = cgD3D9SetUniform (p, data + 8);
break;
case SMP_row3:
case ShaderExpansion::SMP_row3:
hr = cgD3D9SetUniform (p, data + 12);
break;
case SMP_col0:
case ShaderExpansion::SMP_col0:
v[0] = data[0]; v[1] = data[4]; v[2] = data[8]; v[3] = data[12];
hr = cgD3D9SetUniform (p, v);
break;
case SMP_col1:
case ShaderExpansion::SMP_col1:
v[0] = data[1]; v[1] = data[5]; v[2] = data[9]; v[3] = data[13];
hr = cgD3D9SetUniform (p, v);
break;
case SMP_col2:
case ShaderExpansion::SMP_col2:
v[0] = data[2]; v[1] = data[6]; v[2] = data[10]; v[3] = data[14];
hr = cgD3D9SetUniform (p, v);
break;
case SMP_col3:
case ShaderExpansion::SMP_col3:
v[0] = data[3]; v[1] = data[7]; v[2] = data[11]; v[3] = data[15];
hr = cgD3D9SetUniform (p, v);
break;
default:
dxgsg9_cat.error()
<< "issue_parameters ( ) SMP parameter type not implemented " << _mat_spec[i]._piece << "\n";
<< "issue_parameters ( ) SMP parameter type not implemented " << _expansion->_mat_spec[i]._piece << "\n";
break;
}
@ -726,14 +387,14 @@ issue_parameters(GSG *gsg, bool altered)
string name = "unnamed";
if (_mat_spec[i]._arg [0]) {
name = _mat_spec[i]._arg [0] -> get_basename ( );
if (_expansion->_mat_spec[i]._arg [0]) {
name = _expansion->_mat_spec[i]._arg [0] -> get_basename ( );
}
dxgsg9_cat.error()
<< "NAME " << name << "\n"
<< "MAT TYPE "
<< _mat_spec[i]._piece
<< _expansion->_mat_spec[i]._piece
<< " cgD3D9SetUniform failed "
<< D3DERRORSTRING(hr);
@ -757,14 +418,9 @@ issue_parameters(GSG *gsg, bool altered)
void CLP(ShaderContext)::
disable_shader_vertex_arrays(GSG *gsg)
{
#ifdef HAVE_CGDX9
if (gsg -> _cg_context) {
for (int i=0; i<(int)_var_spec.size(); i++) {
CGparameter p = (CGparameter)(_var_spec[i]._parameter);
// DO NOTHING, CURRENTLY USING ONLY ONE STREAM SOURCE
}
#ifdef HAVE_CG
if (_cg_context) {
// DO NOTHING, CURRENTLY USING ONLY ONE STREAM SOURCE
}
#endif
}
@ -790,8 +446,8 @@ void CLP(ShaderContext)::
update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
{
if (prev) prev->disable_shader_vertex_arrays(gsg);
#ifdef HAVE_CGDX9
if (gsg -> _cg_context) {
#ifdef HAVE_CG
if (_cg_context) {
#ifdef SUPPORT_IMMEDIATE_MODE
/*
@ -806,7 +462,7 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
const GeomVertexArrayDataPipelineReader *array_reader;
Geom::NumericType numeric_type;
int start, stride, num_values;
int nvarying = _var_spec.size();
int nvarying = _expansion->_var_spec.size();
int stream_index;
VertexElementArray *vertex_element_array;
@ -822,9 +478,9 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
#endif
for (int i=0; i<nvarying; i++) {
CGparameter p = (CGparameter)(_var_spec[i]._parameter);
InternalName *name = _var_spec[i]._name;
int texslot = _var_spec[i]._append_uv;
CGparameter p = _cg_parameter_map[_expansion->_var_spec[i]._id._seqno];
InternalName *name = _expansion->_var_spec[i]._name;
int texslot = _expansion->_var_spec[i]._append_uv;
if (texslot >= 0) {
const Geom::ActiveTextureStages &active_stages =
gsg->_state._texture->get_on_stages();
@ -982,8 +638,8 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
state = vertex_element_array -> add_end_vertex_element ( );
if (state) {
if (_cg_shader) {
if (cgD3D9ValidateVertexDeclaration (_cg_program [SHADER_type_vert],
if (_cg_context) {
if (cgD3D9ValidateVertexDeclaration (_cg_vprogram,
vertex_element_array -> vertex_element_array) == CG_TRUE) {
dxgsg9_cat.debug() << "|||||cgD3D9ValidateVertexDeclaration succeeded\n";
}
@ -1013,7 +669,7 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
}
}
}
#endif // HAVE_CGDX9
#endif // HAVE_CG
}
////////////////////////////////////////////////////////////////////
@ -1024,10 +680,10 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
void CLP(ShaderContext)::
disable_shader_texture_bindings(GSG *gsg)
{
#ifdef HAVE_CGDX9
if (gsg -> _cg_context) {
for (int i=0; i<(int)_tex_spec.size(); i++) {
CGparameter p = (CGparameter)(_tex_spec[i]._parameter);
#ifdef HAVE_CG
if (_cg_context) {
for (int i=0; i<(int)_expansion->_tex_spec.size(); i++) {
CGparameter p = _cg_parameter_map[_expansion->_tex_spec[i]._id._seqno];
int texunit = cgGetParameterResourceIndex(p);
HRESULT hr;
@ -1061,40 +717,40 @@ update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg)
{
if (prev) prev->disable_shader_texture_bindings(gsg);
#ifdef HAVE_CGDX9
if (gsg -> _cg_context) {
for (int i=0; i<(int)_tex_spec.size(); i++) {
CGparameter p = (CGparameter)(_tex_spec[i]._parameter);
#ifdef HAVE_CG
if (_cg_context) {
for (int i=0; i<(int)_expansion->_tex_spec.size(); i++) {
CGparameter p = _cg_parameter_map[_expansion->_tex_spec[i]._id._seqno];
Texture *tex = 0;
InternalName *id = _tex_spec[i]._name;
InternalName *id = _expansion->_tex_spec[i]._name;
if (id != 0) {
const ShaderInput *input = gsg->_target._shader->get_shader_input(id);
tex = input->get_texture();
} else {
if (_tex_spec[i]._stage >= gsg->_target._texture->get_num_on_stages()) {
if (_expansion->_tex_spec[i]._stage >= gsg->_target._texture->get_num_on_stages()) {
continue;
}
TextureStage *stage = gsg->_target._texture->get_on_stage(_tex_spec[i]._stage);
TextureStage *stage = gsg->_target._texture->get_on_stage(_expansion->_tex_spec[i]._stage);
tex = gsg->_target._texture->get_on_texture(stage);
}
if (_tex_spec[i]._suffix != 0) {
if (_expansion->_tex_spec[i]._suffix != 0) {
// The suffix feature is inefficient. It is a temporary hack.
if (tex == 0) {
continue;
}
tex = tex->load_related(_tex_spec[i]._suffix);
tex = tex->load_related(_expansion->_tex_spec[i]._suffix);
}
if ((tex == 0) || (tex->get_texture_type() != _tex_spec[i]._desired_type)) {
if ((tex == 0) || (tex->get_texture_type() != _expansion->_tex_spec[i]._desired_type)) {
continue;
}
TextureContext *tc = tex->prepare_now(gsg->_prepared_objects, gsg);
// TextureContext *tc = tex->prepare_now(gsg->get_prepared_objects(), gsg);
// TextureContext *tc = tex->prepare_now(gsg->get_prepared_objects(), gsg);
if (tc == (TextureContext*)NULL) {
continue;
}
int texunit = cgGetParameterResourceIndex(p);
gsg->apply_texture(texunit, tc);
}
}

View File

@ -21,11 +21,6 @@
#include "dtool_config.h"
#include "pandabase.h"
#ifdef HAVE_CGDX9
#include "Cg/cg.h"
#include "Cg/cgGL.h"
#include "Cg/cgD3D9.h"
#endif
#include "string_utils.h"
#include "internalName.h"
#include "shaderExpansion.h"
@ -39,47 +34,49 @@
class VertexElementArray;
class CLP(GraphicsStateGuardian);
typedef struct
{
int vertex_shader;
int total_constant_descriptions;
D3DXCONSTANT_DESC *constant_description_array;
}
DX_PARAMETER;
typedef struct
{
int state;
union
{
DIRECT_3D_VERTEX_SHADER direct_3d_vertex_shader;
DIRECT_3D_PIXEL_SHADER direct_3d_pixel_shader;
};
LPD3DXCONSTANTTABLE constant_table;
D3DXCONSTANTTABLE_DESC constant_table_description;
int total_semantics;
D3DXSEMANTIC *semantic_array;
}
DIRECT_3D_SHADER;
// Caution: adding HLSL support is going to be tricky, as the parsing needs
// to be done in the cull thread, which cannot use the DX API. - Josh
//
//
// typedef struct
// {
// int vertex_shader;
// int total_constant_descriptions;
// D3DXCONSTANT_DESC *constant_description_array;
// }
// DX_PARAMETER;
//
// typedef struct
// {
// int state;
// union
// {
// DIRECT_3D_VERTEX_SHADER direct_3d_vertex_shader;
// DIRECT_3D_PIXEL_SHADER direct_3d_pixel_shader;
// };
// LPD3DXCONSTANTTABLE constant_table;
// D3DXCONSTANTTABLE_DESC constant_table_description;
//
// int total_semantics;
// D3DXSEMANTIC *semantic_array;
// }
// DIRECT_3D_SHADER;
////////////////////////////////////////////////////////////////////
// Class : DXShaderContext9
// Description : xyz
////////////////////////////////////////////////////////////////////
typedef CLP(GraphicsStateGuardian) GSG;
class EXPCL_PANDADX CLP(ShaderContext): public ShaderContext {
public:
typedef CLP(GraphicsStateGuardian) GSG;
CLP(ShaderContext)(ShaderExpansion *s, GSG *gsg);
~CLP(ShaderContext)();
INLINE bool valid(GSG *gsg);
bool bind(GSG *gsg);
void unbind(GSG *gsg);
void issue_parameters(GSG *gsg, bool altered);
void issue_transform(GSG *gsg);
void disable_shader_vertex_arrays(GSG *gsg);
@ -87,69 +84,21 @@ public:
void disable_shader_texture_bindings(GSG *gsg);
void update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg);
int _vertex_size;
class VertexElementArray *_vertex_element_array;
// FOR DEBUGGING
int _vertex_size;
string _name;
bool _state;
bool _cg_shader;
bool _transpose_matrix;
private:
#ifdef HAVE_CGDX9
struct ShaderAutoBind {
CGparameter parameter;
int value;
DX_PARAMETER *dx_parameter;
};
struct ShaderArgBind {
CGparameter parameter;
PT(InternalName) name;
DX_PARAMETER *dx_parameter;
};
struct ShaderTexBind {
CGparameter parameter;
PT(InternalName) name;
int stage;
int desiredtype;
PT(InternalName) suffix;
DX_PARAMETER *dx_parameter;
};
struct ShaderTransBind {
CGparameter parameter;
PT(InternalName) src_name;
PT(InternalName) rel_name;
int trans_piece;
DX_PARAMETER *dx_parameter;
};
struct ShaderVarying {
CGparameter parameter;
PT(InternalName) name;
int append_uv;
DX_PARAMETER *dx_parameter;
};
// CGcontext _cg_context;
CGprofile _cg_profile[2];
CGprogram _cg_program[2];
void report_cg_compile_errors(const string &file, CGcontext ctx);
bool try_cg_compile(ShaderExpansion *s, GSG *gsg);
void suggest_cg_profile(const string &vpro, const string &fpro);
CGprofile parse_cg_profile(const string &id, bool vertex);
#ifdef HAVE_CG
CGcontext _cg_context;
CGprogram _cg_vprogram;
CGprogram _cg_fprogram;
pvector <CGparameter> _cg_parameter_map;
#endif
public:
DIRECT_3D_SHADER _direct_3d_vertex_shader;
DIRECT_3D_SHADER _direct_3d_pixel_shader;
int _total_dx_parameters;
DX_PARAMETER *_dx_parameter_array;
private:
void release_resources(void);

View File

@ -50,6 +50,10 @@
#include "indirectLess.h"
#include "pStatTimer.h"
#ifdef HAVE_CG
#include "Cg/cgGL.h"
#endif
#include <algorithm>
#define DEBUG_BUFFERS false
@ -669,10 +673,14 @@ reset() {
}
}
#ifdef HAVE_CGGL
#ifdef HAVE_CG
if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1) &&
cgGLIsProfileSupported(CG_PROFILE_ARBVP1)) {
_supports_basic_shaders = true;
_shader_caps._active_vprofile = (int)cgGLGetLatestProfile(CG_GL_VERTEX);
_shader_caps._active_fprofile = (int)cgGLGetLatestProfile(CG_GL_FRAGMENT);
_shader_caps._ultimate_vprofile = (int)CG_PROFILE_VP40;
_shader_caps._ultimate_fprofile = (int)CG_PROFILE_FP40;
}
#endif
@ -1076,7 +1084,7 @@ reset() {
void gl_set_stencil_functions (StencilRenderStates *stencil_render_states);
gl_set_stencil_functions (_stencil_render_states);
#ifdef HAVE_CGGL
#ifdef HAVE_CG
typedef struct
{
@ -3357,7 +3365,7 @@ do_issue_shader() {
ShaderExpansion *expansion = _target_rs->get_shader_expansion();
if (expansion == 0) {
if (_target._shader->get_shader() != 0) {
expansion = _target._shader->get_shader()->macroexpand(_target_rs);
expansion = _target._shader->get_shader()->macroexpand(_target_rs, _shader_caps);
// I am casting away the const-ness of this pointer, because
// the 'shader-expansion' field is just a cache.
((RenderState *)((const RenderState*)_target_rs))->

View File

@ -27,8 +27,8 @@
////////////////////////////////////////////////////////////////////
INLINE bool CLP(ShaderContext)::
valid() {
#ifdef HAVE_CGGL
if (_state && _cg_context) return true;
#ifdef HAVE_CG
if (_cg_context) return true;
#endif
return false;
}

View File

@ -16,49 +16,14 @@
//
////////////////////////////////////////////////////////////////////
#ifdef HAVE_CG
#include "Cg/cgGL.h"
#endif
#define DEBUG_GL_SHADER 0
TypeHandle CLP(ShaderContext)::_type_handle;
#ifdef HAVE_CGGL
////////////////////////////////////////////////////////////////////
// Function: cg_type_to_panda_type
// Access: Public, Static
// Description: convert a cg shader-arg type to a panda shader-arg type.
////////////////////////////////////////////////////////////////////
static ShaderContext::ShaderArgType
cg_type_to_panda_type(CGtype n) {
switch (n) {
case CG_FLOAT1: return ShaderContext::SAT_float1;
case CG_FLOAT2: return ShaderContext::SAT_float2;
case CG_FLOAT3: return ShaderContext::SAT_float3;
case CG_FLOAT4: return ShaderContext::SAT_float4;
case CG_FLOAT4x4: return ShaderContext::SAT_float4x4;
case CG_SAMPLER1D: return ShaderContext::SAT_sampler1d;
case CG_SAMPLER2D: return ShaderContext::SAT_sampler2d;
case CG_SAMPLER3D: return ShaderContext::SAT_sampler3d;
case CG_SAMPLERCUBE: return ShaderContext::SAT_samplercube;
default: return ShaderContext::SAT_unknown;
}
}
#endif // HAVE_CGGL
#ifdef HAVE_CGGL
////////////////////////////////////////////////////////////////////
// Function: cg_dir_to_panda_dir
// Access: Public, Static
// Description: convert a cg shader-arg type to a panda shader-arg type.
////////////////////////////////////////////////////////////////////
static ShaderContext::ShaderArgDir
cg_dir_to_panda_dir(CGenum n) {
switch (n) {
case CG_IN: return ShaderContext::SAD_in;
case CG_OUT: return ShaderContext::SAD_out;
case CG_INOUT: return ShaderContext::SAD_inout;
default: return ShaderContext::SAD_unknown;
}
}
#endif // HAVE_CGGL
////////////////////////////////////////////////////////////////////
// Function: GLShaderContext::Constructor
@ -67,311 +32,34 @@ cg_dir_to_panda_dir(CGenum n) {
////////////////////////////////////////////////////////////////////
CLP(ShaderContext)::
CLP(ShaderContext)(ShaderExpansion *s, GSG *gsg) : ShaderContext(s) {
string header;
s->parse_init();
s->parse_line(header, true, true);
#ifdef HAVE_CG
if (s->get_header() == "//Cg") {
// Ask the shader expansion to compile itself for us and
// to give us the resulting Cg program objects.
_state = false;
#ifdef HAVE_CGGL
_cg_context = (CGcontext)0;
_cg_profile[SHADER_type_vert] = CG_PROFILE_UNKNOWN;
_cg_profile[SHADER_type_frag] = CG_PROFILE_UNKNOWN;
_cg_program[SHADER_type_vert] = (CGprogram)0;
_cg_program[SHADER_type_frag] = (CGprogram)0;
_cg_program[2] = (CGprogram)0;
if (header == "//Cg") {
// Create the Cg context.
_cg_context = cgCreateContext();
if (_cg_context == 0) {
release_resources();
GLCAT.error() << "Cg not supported by this video card.\n";
if (!s->cg_compile_for(gsg->_shader_caps,
_cg_context,
_cg_vprogram,
_cg_fprogram,
_cg_parameter_map)) {
return;
}
// Parse any directives in the source.
string directive;
while (!s->parse_eof()) {
s->parse_line(directive, true, true);
vector_string pieces;
tokenize(directive, pieces, " \t");
if ((pieces.size()==4)&&(pieces[0]=="//Cg")&&(pieces[1]=="profile")) {
suggest_cg_profile(pieces[2], pieces[3]);
}
}
// Select a profile if no preferred profile specified in the source.
if (_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN) {
_cg_profile[SHADER_type_vert] = cgGLGetLatestProfile(CG_GL_VERTEX);
}
if (_cg_profile[SHADER_type_frag] == CG_PROFILE_UNKNOWN) {
_cg_profile[SHADER_type_frag] = cgGLGetLatestProfile(CG_GL_FRAGMENT);
}
// If we still haven't chosen a profile, give up.
if ((_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN)||
(_cg_profile[SHADER_type_frag] == CG_PROFILE_UNKNOWN)) {
// Load the program.
cgGLLoadProgram(_cg_vprogram);
CGerror verror = cgGetError();
cgGLLoadProgram(_cg_fprogram);
CGerror ferror = cgGetError();
if ((verror != CG_NO_ERROR)||(ferror != CG_NO_ERROR)) {
GLCAT.error() << "Could not load Cg shader:" << s->get_name() << "\n";
release_resources();
GLCAT.error() << "Cg not supported by this video card.\n";
return;
}
// Compile the program.
try_cg_compile(s, gsg);
return;
}
#endif
GLCAT.error() << s->get_name() << ": unrecognized shader language " << header << "\n";
}
#ifdef HAVE_CGGL
////////////////////////////////////////////////////////////////////
// Function: Shader::report_cg_compile_errors
// Access: Public, Static
// Description: Used only after a Cg compile command, to print
// out any error messages that may have occurred
// during the Cg shader compilation. The 'file'
// is the name of the file containing the Cg code.
////////////////////////////////////////////////////////////////////
void CLP(ShaderContext)::
report_cg_compile_errors(const string &file, CGcontext ctx)
{
CGerror err = cgGetError();
if (err != CG_NO_ERROR) {
if (err == CG_COMPILER_ERROR) {
string listing = cgGetLastListing(ctx);
vector_string errlines;
tokenize(listing, errlines, "\n");
for (int i=0; i<(int)errlines.size(); i++) {
string line = trim(errlines[i]);
if (line != "") {
GLCAT.error() << file << " " << errlines[i] << "\n";
}
}
} else {
GLCAT.error() << file << ": " << cgGetErrorString(err) << "\n";
}
}
}
#endif // HAVE_CGGL
////////////////////////////////////////////////////////////////////
// Function: GLShaderContext::suggest_cg_profile
// Access: Private
// Description: xyz
////////////////////////////////////////////////////////////////////
#ifdef HAVE_CGGL
void CLP(ShaderContext)::
suggest_cg_profile(const string &vpro, const string &fpro)
{
// If a good profile has already been suggested, ignore suggestion.
if ((_cg_profile[SHADER_type_vert] != CG_PROFILE_UNKNOWN)||
(_cg_profile[SHADER_type_frag] != CG_PROFILE_UNKNOWN)) {
return;
}
// Parse the suggestion. If not parseable, print error and ignore.
_cg_profile[SHADER_type_vert] = parse_cg_profile(vpro, true);
_cg_profile[SHADER_type_frag] = parse_cg_profile(fpro, false);
if ((_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN)||
(_cg_profile[SHADER_type_frag] == CG_PROFILE_UNKNOWN)) {
GLCAT.error() << "Cg: unrecognized profile name: " << vpro << " " << fpro << "\n";
_cg_profile[SHADER_type_vert] = CG_PROFILE_UNKNOWN;
_cg_profile[SHADER_type_frag] = CG_PROFILE_UNKNOWN;
return;
}
// If the suggestion is parseable, but not supported, ignore silently.
if ((!cgGLIsProfileSupported(_cg_profile[SHADER_type_vert]))||
(!cgGLIsProfileSupported(_cg_profile[SHADER_type_frag]))) {
_cg_profile[SHADER_type_vert] = CG_PROFILE_UNKNOWN;
_cg_profile[SHADER_type_frag] = CG_PROFILE_UNKNOWN;
return;
}
}
#endif
////////////////////////////////////////////////////////////////////
// Function: GLShaderContext::parse_cg_profile
// Access: Private
// Description: xyz
////////////////////////////////////////////////////////////////////
#ifdef HAVE_CGGL
CGprofile CLP(ShaderContext)::
parse_cg_profile(const string &id, bool vertex)
{
int nvprofiles = 4;
int nfprofiles = 4;
CGprofile vprofiles[] = { CG_PROFILE_ARBVP1, CG_PROFILE_VP20, CG_PROFILE_VP30, CG_PROFILE_VP40 };
CGprofile fprofiles[] = { CG_PROFILE_ARBFP1, CG_PROFILE_FP20, CG_PROFILE_FP30, CG_PROFILE_FP40 };
if (vertex) {
for (int i=0; i<nvprofiles; i++) {
if (id == cgGetProfileString(vprofiles[i])) {
return vprofiles[i];
}
}
} else {
for (int i=0; i<nfprofiles; i++) {
if (id == cgGetProfileString(fprofiles[i])) {
return fprofiles[i];
}
}
}
return CG_PROFILE_UNKNOWN;
}
#endif // HAVE_CGGL
////////////////////////////////////////////////////////////////////
// Function: GLShaderContext::try_cg_compile
// Access: Private
// Description: xyz
////////////////////////////////////////////////////////////////////
#ifdef HAVE_CGGL
bool CLP(ShaderContext)::
try_cg_compile(ShaderExpansion *s, GSG *gsg)
{
cgGetError();
_cg_program[0] =
cgCreateProgram(_cg_context, CG_SOURCE, s->_text.c_str(),
_cg_profile[0], "vshader", (const char**)NULL);
report_cg_compile_errors(s->get_name(), _cg_context);
cgGetError();
_cg_program[1] =
cgCreateProgram(_cg_context, CG_SOURCE, s->_text.c_str(),
_cg_profile[1], "fshader", (const char**)NULL);
report_cg_compile_errors(s->get_name(), _cg_context);
if ((_cg_program[SHADER_type_vert]==0)||(_cg_program[SHADER_type_frag]==0)) {
release_resources();
return false;
}
bool success = true;
CGparameter parameter;
for (int progindex=0; progindex<2; progindex++) {
int nvtx = _var_spec.size();
for (parameter = cgGetFirstLeafParameter(_cg_program[progindex],CG_PROGRAM);
parameter != 0;
parameter = cgGetNextLeafParameter(parameter)) {
CGenum vbl = cgGetParameterVariability(parameter);
if ((vbl==CG_VARYING)||(vbl==CG_UNIFORM)) {
success &= compile_parameter(parameter,
cgGetParameterName(parameter),
cg_type_to_panda_type(cgGetParameterType(parameter)),
cg_dir_to_panda_dir(cgGetParameterDirection(parameter)),
(vbl == CG_VARYING),
GLCAT.get_safe_ptr());
}
}
if ((progindex == SHADER_type_frag) && (nvtx != _var_spec.size())) {
GLCAT.error() << "Cannot use vtx parameters in an fshader\n";
success = false;
}
}
if (!success) {
release_resources();
return false;
}
// DEBUG: output the generated program
if (GLCAT.is_debug()) {
const char *vertex_program;
const char *pixel_program;
vertex_program = cgGetProgramString (_cg_program[0], CG_COMPILED_PROGRAM);
pixel_program = cgGetProgramString (_cg_program[1], CG_COMPILED_PROGRAM);
GLCAT.debug() << vertex_program << "\n";
GLCAT.debug() << pixel_program << "\n";
}
// The following code is present to work around a bug in the Cg compiler.
// It does not generate correct code for shadow map lookups when using arbfp1.
// This is a particularly onerous limitation, given that arbfp1 is the only
// Cg target that works on radeons. I suspect this is an intentional
// omission on nvidia's part. The following code fetches the output listing,
// detects the error, repairs the code, and resumbits the repaired code to Cg.
if ((_cg_profile[1] == CG_PROFILE_ARBFP1) && (gsg->_supports_shadow_filter)) {
bool shadowunit[32];
bool anyshadow = false;
memset(shadowunit, 0, sizeof(shadowunit));
vector_string lines;
tokenize(cgGetProgramString(_cg_program[SHADER_type_frag],
CG_COMPILED_PROGRAM), lines, "\n");
// figure out which texture units contain shadow maps.
for (int lineno=0; lineno<(int)lines.size(); lineno++) {
if (lines[lineno].compare(0,21,"#var sampler2DSHADOW ")) {
continue;
}
vector_string fields;
tokenize(lines[lineno], fields, ":");
if (fields.size()!=5) {
continue;
}
vector_string words;
tokenize(trim(fields[2]), words, " ");
if (words.size()!=2) {
continue;
}
int unit = atoi(words[1].c_str());
if ((unit < 0)||(unit >= 32)) {
continue;
}
anyshadow = true;
shadowunit[unit] = true;
}
// modify all TEX statements that use the relevant texture units.
if (anyshadow) {
for (int lineno=0; lineno<(int)lines.size(); lineno++) {
if (lines[lineno].compare(0,4,"TEX ")) {
continue;
}
vector_string fields;
tokenize(lines[lineno], fields, ",");
if ((fields.size()!=4)||(trim(fields[3]) != "2D;")) {
continue;
}
vector_string texunitf;
tokenize(trim(fields[2]), texunitf, "[]");
if ((texunitf.size()!=3)||(texunitf[0] != "texture")||(texunitf[2]!="")) {
continue;
}
int unit = atoi(texunitf[1].c_str());
if ((unit < 0) || (unit >= 32) || (shadowunit[unit]==false)) {
continue;
}
lines[lineno] = fields[0]+","+fields[1]+","+fields[2]+", SHADOW2D;";
}
string result = "!!ARBfp1.0\nOPTION ARB_fragment_program_shadow;\n";
for (int lineno=1; lineno<(int)lines.size(); lineno++) {
result += (lines[lineno] + "\n");
}
_cg_program[2] = _cg_program[SHADER_type_frag];
_cg_program[SHADER_type_frag] =
cgCreateProgram(_cg_context, CG_OBJECT, result.c_str(),
_cg_profile[SHADER_type_frag], "fshader", (const char**)NULL);
report_cg_compile_errors(s->get_name(), _cg_context);
if (_cg_program[SHADER_type_frag]==0) {
release_resources();
return false;
}
}
}
cgGLLoadProgram(_cg_program[SHADER_type_vert]);
report_cg_compile_errors(s->get_name(), _cg_context);
cgGLLoadProgram(_cg_program[SHADER_type_frag]);
report_cg_compile_errors(s->get_name(), _cg_context);
_state = true;
return true;
}
#endif
////////////////////////////////////////////////////////////////////
// Function: GLShaderContext::Destructor
// Access: Public
@ -390,15 +78,13 @@ CLP(ShaderContext)::
////////////////////////////////////////////////////////////////////
void CLP(ShaderContext)::
release_resources() {
#ifdef HAVE_CGGL
#ifdef HAVE_CG
if (_cg_context) {
cgDestroyContext(_cg_context);
_cg_context = (CGcontext)0;
_cg_profile[SHADER_type_vert] = (CGprofile)0;
_cg_profile[SHADER_type_frag] = (CGprofile)0;
_cg_program[SHADER_type_vert] = (CGprogram)0;
_cg_program[SHADER_type_frag] = (CGprogram)0;
_cg_program[2] = (CGprogram)0;
_cg_context = 0;
_cg_vprogram = 0;
_cg_fprogram = 0;
_cg_parameter_map.clear();
}
#endif
}
@ -412,17 +98,17 @@ release_resources() {
////////////////////////////////////////////////////////////////////
void CLP(ShaderContext)::
bind(GSG *gsg) {
#ifdef HAVE_CGGL
#ifdef HAVE_CG
if (_cg_context != 0) {
// Pass in k-parameters and transform-parameters
issue_parameters(gsg, true);
// Bind the shaders.
cgGLEnableProfile(_cg_profile[SHADER_type_vert]);
cgGLBindProgram(_cg_program[SHADER_type_vert]);
cgGLEnableProfile(_cg_profile[SHADER_type_frag]);
cgGLBindProgram(_cg_program[SHADER_type_frag]);
cgGLEnableProfile(cgGetProgramProfile(_cg_vprogram));
cgGLBindProgram(_cg_vprogram);
cgGLEnableProfile(cgGetProgramProfile(_cg_fprogram));
cgGLBindProgram(_cg_fprogram);
}
#endif
}
@ -434,10 +120,10 @@ bind(GSG *gsg) {
////////////////////////////////////////////////////////////////////
void CLP(ShaderContext)::
unbind() {
#ifdef HAVE_CGGL
#ifdef HAVE_CG
if (_cg_context != 0) {
cgGLDisableProfile(_cg_profile[SHADER_type_vert]);
cgGLDisableProfile(_cg_profile[SHADER_type_frag]);
cgGLDisableProfile(cgGetProgramProfile(_cg_vprogram));
cgGLDisableProfile(cgGetProgramProfile(_cg_fprogram));
}
#endif
}
@ -459,28 +145,28 @@ unbind() {
////////////////////////////////////////////////////////////////////
void CLP(ShaderContext)::
issue_parameters(GSG *gsg, bool altered) {
#ifdef HAVE_CGGL
#ifdef HAVE_CG
if (_cg_context == 0) {
return;
}
for (int i=0; i<(int)_mat_spec.size(); i++) {
if (altered || _mat_spec[i]._trans_dependent) {
CGparameter p = (CGparameter)(_mat_spec[i]._parameter);
const LMatrix4f *val = gsg->fetch_specified_value(_mat_spec[i], altered);
for (int i=0; i<(int)_expansion->_mat_spec.size(); i++) {
if (altered || _expansion->_mat_spec[i]._trans_dependent) {
CGparameter p = _cg_parameter_map[_expansion->_mat_spec[i]._id._seqno];
const LMatrix4f *val = gsg->fetch_specified_value(_expansion->_mat_spec[i], altered);
if (val) {
const float *data = val->get_data();
switch (_mat_spec[i]._piece) {
case SMP_whole: cgGLSetMatrixParameterfc(p, data); break;
case SMP_transpose: cgGLSetMatrixParameterfr(p, data); break;
case SMP_row0: cgGLSetParameter4fv(p, data+ 0); break;
case SMP_row1: cgGLSetParameter4fv(p, data+ 4); break;
case SMP_row2: cgGLSetParameter4fv(p, data+ 8); break;
case SMP_row3: cgGLSetParameter4fv(p, data+12); break;
case SMP_col0: cgGLSetParameter4f(p, data[0], data[4], data[ 8], data[12]); break;
case SMP_col1: cgGLSetParameter4f(p, data[1], data[5], data[ 9], data[13]); break;
case SMP_col2: cgGLSetParameter4f(p, data[2], data[6], data[10], data[14]); break;
case SMP_col3: cgGLSetParameter4f(p, data[3], data[7], data[11], data[15]); break;
switch (_expansion->_mat_spec[i]._piece) {
case ShaderExpansion::SMP_whole: cgGLSetMatrixParameterfc(p, data); break;
case ShaderExpansion::SMP_transpose: cgGLSetMatrixParameterfr(p, data); break;
case ShaderExpansion::SMP_row0: cgGLSetParameter4fv(p, data+ 0); break;
case ShaderExpansion::SMP_row1: cgGLSetParameter4fv(p, data+ 4); break;
case ShaderExpansion::SMP_row2: cgGLSetParameter4fv(p, data+ 8); break;
case ShaderExpansion::SMP_row3: cgGLSetParameter4fv(p, data+12); break;
case ShaderExpansion::SMP_col0: cgGLSetParameter4f(p, data[0], data[4], data[ 8], data[12]); break;
case ShaderExpansion::SMP_col1: cgGLSetParameter4f(p, data[1], data[5], data[ 9], data[13]); break;
case ShaderExpansion::SMP_col2: cgGLSetParameter4f(p, data[2], data[6], data[10], data[14]); break;
case ShaderExpansion::SMP_col3: cgGLSetParameter4f(p, data[3], data[7], data[11], data[15]); break;
}
}
}
@ -495,13 +181,13 @@ issue_parameters(GSG *gsg, bool altered) {
////////////////////////////////////////////////////////////////////
void CLP(ShaderContext)::
disable_shader_vertex_arrays(GSG *gsg) {
#ifdef HAVE_CGGL
#ifdef HAVE_CG
if (_cg_context == 0) {
return;
}
for (int i=0; i<(int)_var_spec.size(); i++) {
CGparameter p = (CGparameter)(_var_spec[i]._parameter);
for (int i=0; i<(int)_expansion->_var_spec.size(); i++) {
CGparameter p = _cg_parameter_map[_expansion->_var_spec[i]._id._seqno];
cgGLDisableClientState(p);
}
#endif
@ -521,7 +207,7 @@ disable_shader_vertex_arrays(GSG *gsg) {
void CLP(ShaderContext)::
update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg) {
if (prev) prev->disable_shader_vertex_arrays(gsg);
#ifdef HAVE_CGGL
#ifdef HAVE_CG
if (_cg_context == 0) {
return;
}
@ -535,11 +221,11 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg) {
const GeomVertexArrayDataPipelineReader *array_reader;
Geom::NumericType numeric_type;
int start, stride, num_values;
int nvarying = _var_spec.size();
int nvarying = _expansion->_var_spec.size();
for (int i=0; i<nvarying; i++) {
CGparameter p = (CGparameter)(_var_spec[i]._parameter);
InternalName *name = _var_spec[i]._name;
int texslot = _var_spec[i]._append_uv;
CGparameter p = _cg_parameter_map[_expansion->_var_spec[i]._id._seqno];
InternalName *name = _expansion->_var_spec[i]._name;
int texslot = _expansion->_var_spec[i]._append_uv;
if (texslot >= 0) {
const Geom::ActiveTextureStages &active_stages =
gsg->_state._texture->get_on_stages();
@ -566,7 +252,7 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg) {
}
}
}
#endif // HAVE_CGGL
#endif // HAVE_CG
}
////////////////////////////////////////////////////////////////////
@ -576,13 +262,13 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg) {
////////////////////////////////////////////////////////////////////
void CLP(ShaderContext)::
disable_shader_texture_bindings(GSG *gsg) {
#ifdef HAVE_CGGL
#ifdef HAVE_CG
if (_cg_context == 0) {
return;
}
for (int i=0; i<(int)_tex_spec.size(); i++) {
CGparameter p = (CGparameter)(_tex_spec[i]._parameter);
for (int i=0; i<(int)_expansion->_tex_spec.size(); i++) {
CGparameter p = _cg_parameter_map[_expansion->_tex_spec[i]._id._seqno];
int texunit = cgGetParameterResourceIndex(p);
gsg->_glActiveTexture(GL_TEXTURE0 + texunit);
GLP(Disable)(GL_TEXTURE_1D);
@ -613,33 +299,33 @@ disable_shader_texture_bindings(GSG *gsg) {
void CLP(ShaderContext)::
update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg) {
if (prev) prev->disable_shader_texture_bindings(gsg);
#ifdef HAVE_CGGL
#ifdef HAVE_CG
if (_cg_context == 0) {
return;
}
for (int i=0; i<(int)_tex_spec.size(); i++) {
CGparameter p = (CGparameter)(_tex_spec[i]._parameter);
for (int i=0; i<(int)_expansion->_tex_spec.size(); i++) {
CGparameter p = _cg_parameter_map[_expansion->_tex_spec[i]._id._seqno];
Texture *tex = 0;
InternalName *id = _tex_spec[i]._name;
InternalName *id = _expansion->_tex_spec[i]._name;
if (id != 0) {
const ShaderInput *input = gsg->_target._shader->get_shader_input(id);
tex = input->get_texture();
} else {
if (_tex_spec[i]._stage >= gsg->_target._texture->get_num_on_stages()) {
if (_expansion->_tex_spec[i]._stage >= gsg->_target._texture->get_num_on_stages()) {
continue;
}
TextureStage *stage = gsg->_target._texture->get_on_stage(_tex_spec[i]._stage);
TextureStage *stage = gsg->_target._texture->get_on_stage(_expansion->_tex_spec[i]._stage);
tex = gsg->_target._texture->get_on_texture(stage);
}
if (_tex_spec[i]._suffix != 0) {
if (_expansion->_tex_spec[i]._suffix != 0) {
// The suffix feature is inefficient. It is a temporary hack.
if (tex == 0) {
continue;
}
tex = tex->load_related(_tex_spec[i]._suffix);
tex = tex->load_related(_expansion->_tex_spec[i]._suffix);
}
if ((tex == 0) || (tex->get_texture_type() != _tex_spec[i]._desired_type)) {
if ((tex == 0) || (tex->get_texture_type() != _expansion->_tex_spec[i]._desired_type)) {
continue;
}
TextureContext *tc = tex->prepare_now(gsg->_prepared_objects, gsg);

View File

@ -17,9 +17,6 @@
////////////////////////////////////////////////////////////////////
#include "pandabase.h"
#ifdef HAVE_CGGL
#include "Cg/cgGL.h"
#endif
#include "string_utils.h"
#include "internalName.h"
#include "shaderExpansion.h"
@ -49,23 +46,18 @@ public:
void update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg);
void disable_shader_texture_bindings(GSG *gsg);
void update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg);
bool _state;
private:
#ifdef HAVE_CGGL
#ifdef HAVE_CG
CGcontext _cg_context;
CGprofile _cg_profile[2];
CGprogram _cg_program[3];
void report_cg_compile_errors(const string &file, CGcontext ctx);
bool try_cg_compile(ShaderExpansion *s, GSG *gsg);
void suggest_cg_profile(const string &vpro, const string &fpro);
CGprofile parse_cg_profile(const string &id, bool vertex);
CGprogram _cg_vprogram;
CGprogram _cg_fprogram;
pvector <CGparameter> _cg_parameter_map;
#endif
void release_resources(void);
void release_resources(void);
public:
static TypeHandle get_class_type() {
return _type_handle;

View File

@ -1,7 +1,7 @@
#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
dtoolutil:c dtoolbase:c dtool:m prc:c
//#define OSX_SYS_LIBS mx
#define USE_PACKAGES zlib
#define USE_PACKAGES zlib cg
#begin lib_target
#define TARGET gobj

View File

@ -88,7 +88,7 @@ PreparedGraphicsObjects::
sci != _prepared_shaders.end();
++sci) {
ShaderContext *sc = (*sci);
sc->_shader_expansion->clear_prepared(this);
sc->_expansion->clear_prepared(this);
}
_prepared_shaders.clear();
@ -460,12 +460,12 @@ void PreparedGraphicsObjects::
release_shader(ShaderContext *sc) {
ReMutexHolder holder(_lock);
sc->_shader_expansion->clear_prepared(this);
sc->_expansion->clear_prepared(this);
// We have to set the Shader pointer to NULL at this point, since
// the Shader itself might destruct at any time after it has been
// released.
sc->_shader_expansion = (ShaderExpansion *)NULL;
sc->_expansion = (ShaderExpansion *)NULL;
bool removed = (_prepared_shaders.erase(sc) != 0);
nassertv(removed);
@ -492,8 +492,8 @@ release_all_shaders() {
sci != _prepared_shaders.end();
++sci) {
ShaderContext *sc = (*sci);
sc->_shader_expansion->clear_prepared(this);
sc->_shader_expansion = (ShaderExpansion *)NULL;
sc->_expansion->clear_prepared(this);
sc->_expansion = (ShaderExpansion *)NULL;
_released_shaders.insert(sc);
}

View File

@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////
INLINE ShaderContext::
ShaderContext(ShaderExpansion *se) :
_shader_expansion(se)
_expansion(se)
{
}

View File

@ -22,678 +22,3 @@
TypeHandle ShaderContext::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: Shader::cp_report_error
// Access: Public
// Description: Generate an error message including a description
// of the specified parameter.
////////////////////////////////////////////////////////////////////
void ShaderContext::
cp_report_error(ShaderArgInfo &p, const string &msg)
{
string vstr;
if (p._varying) vstr = "varying ";
else vstr = "uniform ";
string dstr = "unknown ";
if (p._direction == SAD_in) dstr = "in ";
if (p._direction == SAD_out) dstr = "out ";
if (p._direction == SAD_inout) dstr = "inout ";
string tstr = "invalid ";
switch (p._type) {
case SAT_float1: tstr = "float1 "; break;
case SAT_float2: tstr = "float2 "; break;
case SAT_float3: tstr = "float3 "; break;
case SAT_float4: tstr = "float4 "; break;
case SAT_float4x4: tstr = "float4x4 "; break;
case SAT_sampler1d: tstr = "sampler1d "; break;
case SAT_sampler2d: tstr = "sampler2d "; break;
case SAT_sampler3d: tstr = "sampler3d "; break;
case SAT_samplercube: tstr = "samplercube "; break;
case SAT_unknown: tstr = "unknown "; break;
}
string fn = _shader_expansion->get_name();
p._cat->error() << fn << ": " << msg << " (" <<
vstr << dstr << tstr << p._name << ")\n";
}
////////////////////////////////////////////////////////////////////
// Function: Shader::cp_errchk_parameter_words
// Access: Public, Static
// Description: Make sure the provided parameter contains
// the specified number of words. If not, print
// error message and return false.
////////////////////////////////////////////////////////////////////
bool ShaderContext::
cp_errchk_parameter_words(ShaderArgInfo &p, int len)
{
vector_string words;
tokenize(p._name, words, "_");
if ((int)words.size() != len) {
cp_report_error(p, "parameter name has wrong number of words");
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: Shader::cp_errchk_parameter_in
// Access: Public, Static
// Description: Make sure the provided parameter has the
// 'in' direction. If not, print
// error message and return false.
////////////////////////////////////////////////////////////////////
bool ShaderContext::
cp_errchk_parameter_in(ShaderArgInfo &p)
{
if (p._direction != SAD_in) {
cp_report_error(p, "parameter should be declared 'in'");
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: Shader::cp_errchk_parameter_varying
// Access: Public, Static
// Description: Make sure the provided parameter has the
// correct variance. If not, print
// error message and return false.
////////////////////////////////////////////////////////////////////
bool ShaderContext::
cp_errchk_parameter_varying(ShaderArgInfo &p)
{
if (!p._varying) {
cp_report_error(p, "parameter should be declared 'varying'");
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: Shader::cp_errchk_parameter_uniform
// Access: Public, Static
// Description: Make sure the provided parameter has the
// correct variance. If not, print
// error message and return false.
////////////////////////////////////////////////////////////////////
bool ShaderContext::
cp_errchk_parameter_uniform(ShaderArgInfo &p)
{
if (p._varying) {
cp_report_error(p, "parameter should be declared 'uniform'");
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: Shader::cp_errchk_parameter_float
// Access: Public, Static
// Description: Make sure the provided parameter has
// a floating point type. If not, print
// error message and return false.
////////////////////////////////////////////////////////////////////
bool ShaderContext::
cp_errchk_parameter_float(ShaderArgInfo &p, int lo, int hi)
{
int nfloat;
switch (p._type) {
case SAT_float1: nfloat = 1; break;
case SAT_float2: nfloat = 2; break;
case SAT_float3: nfloat = 3; break;
case SAT_float4: nfloat = 4; break;
case SAT_float4x4: nfloat = 16; break;
default: nfloat = 0; break;
}
if ((nfloat < lo)||(nfloat > hi)) {
string msg = "wrong type for parameter: should be float";
cp_report_error(p, msg);
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: Shader::cp_errchk_parameter_sampler
// Access: Public, Static
// Description: Make sure the provided parameter has
// a texture type. If not, print
// error message and return false.
////////////////////////////////////////////////////////////////////
bool ShaderContext::
cp_errchk_parameter_sampler(ShaderArgInfo &p)
{
if ((p._type!=SAT_sampler1d)&&
(p._type!=SAT_sampler2d)&&
(p._type!=SAT_sampler3d)&&
(p._type!=SAT_samplercube)) {
cp_report_error(p, "parameter should have a 'sampler' type");
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: ShaderContext::cp_parse_trans_clause
// Access: Public
// Description: Parses a single clause of a "trans" parameter.
////////////////////////////////////////////////////////////////////
bool ShaderContext::
cp_parse_trans_clause(ShaderArgInfo &p, ShaderMatSpec &spec,
int part, const vector_string &pieces,
int &next, ShaderMatInput ofop, ShaderMatInput op) {
if (pieces[next+1]=="of") {
if (pieces[next+2]=="") {
cp_report_error(p, "'of' should be followed by a name");
return false;
}
spec._part[part] = ofop;
spec._arg[part] = InternalName::make(pieces[next+2]);
next += 3;
return true;
} else {
spec._part[part] = op;
spec._arg[part] = NULL;
next += 1;
return true;
}
}
////////////////////////////////////////////////////////////////////
// Function: ShaderContext::cp_optimize_mat_spec
// Access: Public
// Description: Analyzes a ShaderMatSpec and decides what it should
// use its cache for. It can cache the results of any
// one opcode, or, it can cache the entire result. This
// routine needs to be smart enough to know which
// data items can be correctly cached, and which cannot.
////////////////////////////////////////////////////////////////////
void ShaderContext::
cp_optimize_mat_spec(ShaderMatSpec &spec) {
// If we're composing with identity, simplify.
if (spec._func == SMF_compose) {
if (spec._part[1] == SMO_identity) {
spec._func = SMF_first;
}
}
if (spec._func == SMF_compose) {
if (spec._part[0] == SMO_identity) {
spec._func = SMF_first;
spec._part[0] = spec._part[1];
spec._arg[0] = spec._arg[1];
}
}
// See if either half can be cached.
bool can_cache_part0 = true;
bool can_cache_part1 = true;
if ((spec._part[0] == SMO_model_to_view)||
(spec._part[0] == SMO_view_to_model)) {
can_cache_part0 = false;
}
if ((spec._part[1] == SMO_model_to_view)||
(spec._part[1] == SMO_view_to_model)) {
can_cache_part1 = false;
}
// See if we can use a compose-with-cache variant.
if (spec._func == SMF_compose) {
if (can_cache_part0) {
spec._func = SMF_compose_cache_first;
} else if (can_cache_part1) {
spec._func = SMF_compose_cache_second;
}
}
// Determine transform-dependence.
if (can_cache_part0 && can_cache_part1) {
spec._trans_dependent = false;
} else {
spec._trans_dependent = true;
}
}
////////////////////////////////////////////////////////////////////
// Function: ShaderContext::compile_parameter
// Access: Public
// Description: Analyzes a parameter and decides how to
// bind the parameter to some part of panda's
// internal state. Updates one of the bind
// arrays to cause the binding to occur.
//
// If there is an error, this routine will append
// an error message onto the error messages.
////////////////////////////////////////////////////////////////////
bool ShaderContext::
compile_parameter(void *reference,
const string &arg_name,
ShaderArgType arg_type,
ShaderArgDir arg_direction,
bool arg_varying,
NotifyCategory *arg_cat)
{
ShaderArgInfo p;
p._name = arg_name;
p._type = arg_type;
p._direction = arg_direction;
p._varying = arg_varying;
p._cat = arg_cat;
if (p._name.size() == 0) return true;
if (p._name[0] == '$') return true;
vector_string pieces;
tokenize(p._name, pieces, "_");
if (pieces.size() < 2) {
cp_report_error(p, "invalid parameter name");
return false;
}
// Implement vtx parameters - the varying kind.
if (pieces[0] == "vtx") {
if ((!cp_errchk_parameter_in(p)) ||
(!cp_errchk_parameter_varying(p)) ||
(!cp_errchk_parameter_float(p, 1, 4))) {
return false;
}
ShaderVarSpec bind;
bind._parameter = reference;
if (pieces.size() == 2) {
if (pieces[1]=="position") {
bind._name = InternalName::get_vertex();
bind._append_uv = -1;
_var_spec.push_back(bind);
return true;
}
if (pieces[1].substr(0,8)=="texcoord") {
bind._name = InternalName::get_texcoord();
bind._append_uv = atoi(pieces[1].c_str()+8);
_var_spec.push_back(bind);
return true;
}
if (pieces[1].substr(0,7)=="tangent") {
bind._name = InternalName::get_tangent();
bind._append_uv = atoi(pieces[1].c_str()+7);
_var_spec.push_back(bind);
return true;
}
if (pieces[1].substr(0,8)=="binormal") {
bind._name = InternalName::get_binormal();
bind._append_uv = atoi(pieces[1].c_str()+8);
_var_spec.push_back(bind);
return true;
}
}
bind._name = InternalName::get_root();
bind._append_uv = -1;
for (int i=1; i<(int)(pieces.size()-0); i++)
bind._name = bind._name->append(pieces[i]);
_var_spec.push_back(bind);
return true;
}
// Implement some macros. Macros work by altering the
// contents of the 'pieces' array, and then falling through.
if (pieces[0] == "mstrans") {
pieces[0] = "trans";
pieces.push_back("to");
pieces.push_back("model");
}
if (pieces[0] == "wstrans") {
pieces[0] = "trans";
pieces.push_back("to");
pieces.push_back("world");
}
if (pieces[0] == "vstrans") {
pieces[0] = "trans";
pieces.push_back("to");
pieces.push_back("view");
}
if (pieces[0] == "cstrans") {
pieces[0] = "trans";
pieces.push_back("to");
pieces.push_back("clip");
}
if (pieces[0] == "mspos") {
pieces[0] = "row3";
pieces.push_back("to");
pieces.push_back("model");
}
if (pieces[0] == "wspos") {
pieces[0] = "row3";
pieces.push_back("to");
pieces.push_back("world");
}
if (pieces[0] == "vspos") {
pieces[0] = "row3";
pieces.push_back("to");
pieces.push_back("view");
}
if (pieces[0] == "cspos") {
pieces[0] = "row3";
pieces.push_back("to");
pieces.push_back("clip");
}
// Implement the modelview macros.
if ((pieces[0] == "mat")||(pieces[0] == "inv")||
(pieces[0] == "tps")||(pieces[0] == "itp")) {
if (!cp_errchk_parameter_words(p, 2)) {
return false;
}
string trans = pieces[0];
string matrix = pieces[1];
pieces.clear();
if (matrix == "modelview") {
tokenize("trans_model_to_apiview", pieces, "_");
} else if (matrix == "projection") {
tokenize("trans_apiview_to_apiclip", pieces, "_");
} else if (matrix == "modelproj") {
tokenize("trans_model_to_apiclip", pieces, "_");
} else {
cp_report_error(p,"unrecognized matrix name");
return false;
}
if (trans=="mat") {
pieces[0] = "trans";
} else if (trans=="inv") {
string t = pieces[1];
pieces[1] = pieces[3];
pieces[3] = t;
} else if (trans=="tps") {
pieces[0] = "tpose";
} else if (trans=="itp") {
string t = pieces[1];
pieces[1] = pieces[3];
pieces[3] = t;
pieces[0] = "tpose";
}
}
// Implement the transform-matrix generator.
if ((pieces[0]=="trans")||
(pieces[0]=="tpose")||
(pieces[0]=="row0")||
(pieces[0]=="row1")||
(pieces[0]=="row2")||
(pieces[0]=="row3")||
(pieces[0]=="col0")||
(pieces[0]=="col1")||
(pieces[0]=="col2")||
(pieces[0]=="col3")) {
if ((!cp_errchk_parameter_in(p)) ||
(!cp_errchk_parameter_uniform(p)))
return false;
ShaderMatSpec bind;
bind._parameter = reference;
bind._func = SMF_compose;
int next = 1;
pieces.push_back("");
// Decide whether this is a matrix or vector.
if (pieces[0]=="trans") bind._piece = SMP_whole;
else if (pieces[0]=="tpose") bind._piece = SMP_transpose;
else if (pieces[0]=="row0") bind._piece = SMP_row0;
else if (pieces[0]=="row1") bind._piece = SMP_row1;
else if (pieces[0]=="row2") bind._piece = SMP_row2;
else if (pieces[0]=="row3") bind._piece = SMP_row3;
else if (pieces[0]=="col0") bind._piece = SMP_col0;
else if (pieces[0]=="col1") bind._piece = SMP_col1;
else if (pieces[0]=="col2") bind._piece = SMP_col2;
else if (pieces[0]=="col3") bind._piece = SMP_col3;
if ((bind._piece == SMP_whole)||(bind._piece == SMP_transpose)) {
if (!cp_errchk_parameter_float(p, 16, 16)) return false;
} else {
if (!cp_errchk_parameter_float(p, 4, 4)) return false;
}
// Parse the first half of the clause.
bool ok = true;
if ((pieces[next]=="")||(pieces[next]=="of")||(pieces[next]=="to")){
cp_report_error(p, "argument missing");
return false;
} else if (pieces[next] == "world") {
bind._part[0] = SMO_world_to_view;
bind._arg[0] = NULL;
next += 1;
} else if (pieces[next] == "model") {
ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_view_x_to_view, SMO_model_to_view);
} else if (pieces[next] == "clip") {
ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_clip_x_to_view, SMO_clip_to_view);
} else if (pieces[next] == "view") {
ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_view_x_to_view, SMO_identity);
} else if (pieces[next] == "apiview") {
ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_apiview_x_to_view, SMO_apiview_to_view);
} else if (pieces[next] == "apiclip") {
ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_apiclip_x_to_view, SMO_apiclip_to_view);
} else {
bind._part[0] = SMO_view_x_to_view;
bind._arg[0] = InternalName::make(pieces[next]);
next += 1;
}
// Check for errors in the first clause.
if (!ok) {
return false;
}
// Check for syntactic well-formed-ness.
if (pieces[next] != "to") {
cp_report_error(p, "keyword 'to' expected");
return false;
} else {
next += 1;
}
// Parse the second half of the clause.
if ((pieces[next]=="")||(pieces[next]=="of")||(pieces[next]=="to")){
cp_report_error(p, "argument missing");
return false;
} else if (pieces[next] == "world") {
bind._part[1] = SMO_view_to_world;
bind._arg[1] = NULL;
next += 1;
} else if (pieces[next] == "model") {
ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_view_x, SMO_view_to_model);
} else if (pieces[next] == "clip") {
ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_clip_x, SMO_view_to_clip);
} else if (pieces[next] == "view") {
ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_view_x, SMO_identity);
} else if (pieces[next] == "apiview") {
ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_apiview_x, SMO_view_to_apiview);
} else if (pieces[next] == "apiclip") {
ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_apiclip_x, SMO_view_to_apiclip);
} else {
bind._part[1] = SMO_view_to_view_x;
bind._arg[1] = InternalName::make(pieces[next]);
next += 1;
}
// Check for errors in the second clause.
if (!ok) {
return false;
}
// Check for syntactic well-formed-ness.
if (pieces[next] != "") {
cp_report_error(p, "end of line expected");
return false;
}
cp_optimize_mat_spec(bind);
_mat_spec.push_back(bind);
return true;
}
// Keywords to access unusual parameters.
if (pieces[0] == "sys") {
if ((!cp_errchk_parameter_words(p,2)) ||
(!cp_errchk_parameter_in(p)) ||
(!cp_errchk_parameter_uniform(p))) {
return false;
}
ShaderMatSpec bind;
bind._parameter = reference;
bind._piece = SMP_row3;
bind._func = SMF_first;
bind._part[1] = SMO_identity;
bind._arg[1] = NULL;
if (pieces[1] == "pixelsize") {
if (!cp_errchk_parameter_float(p, 2, 2)) {
return false;
}
bind._part[0] = SMO_pixel_size;
bind._arg[0] = NULL;
} else if (pieces[1] == "windowsize") {
if (!cp_errchk_parameter_float(p, 2, 2)) {
return false;
}
bind._part[0] = SMO_window_size;
bind._arg[0] = NULL;
} else if (pieces[1] == "cardcenter") {
if (!cp_errchk_parameter_float(p, 2, 2)) {
return false;
}
bind._part[0] = SMO_card_center;
bind._arg[0] = NULL;
} else {
cp_report_error(p,"unknown system parameter");
return false;
}
cp_optimize_mat_spec(bind);
_mat_spec.push_back(bind);
return true;
}
// Keywords to access textures.
if (pieces[0] == "tex") {
if ((!cp_errchk_parameter_in(p)) ||
(!cp_errchk_parameter_uniform(p)) ||
(!cp_errchk_parameter_sampler(p)))
return false;
if ((pieces.size() != 2)&&(pieces.size() != 3)) {
cp_report_error(p, "Invalid parameter name");
return false;
}
ShaderTexSpec bind;
bind._parameter = reference;
bind._name = 0;
bind._stage = atoi(pieces[1].c_str());
switch (p._type) {
case SAT_sampler1d: bind._desired_type = Texture::TT_1d_texture; break;
case SAT_sampler2d: bind._desired_type = Texture::TT_2d_texture; break;
case SAT_sampler3d: bind._desired_type = Texture::TT_3d_texture; break;
case SAT_samplercube: bind._desired_type = Texture::TT_cube_map; break;
default:
cp_report_error(p, "Invalid type for a tex-parameter");
return false;
}
if (pieces.size()==3) {
bind._suffix = InternalName::make(((string)"-") + pieces[2]);
}
_tex_spec.push_back(bind);
return true;
}
// Keywords to access constants.
if (pieces[0] == "k") {
if ((!cp_errchk_parameter_words(p,2)) ||
(!cp_errchk_parameter_in(p)) ||
(!cp_errchk_parameter_uniform(p)))
return false;
switch (p._type) {
case SAT_float4: {
ShaderMatSpec bind;
bind._parameter = reference;
bind._piece = SMP_row3;
bind._func = SMF_first;
bind._part[0] = SMO_vec_constant_x;
bind._arg[0] = InternalName::make(pieces[1]);
bind._part[1] = SMO_identity;
bind._arg[1] = NULL;
cp_optimize_mat_spec(bind);
_mat_spec.push_back(bind);
break;
}
case SAT_float4x4: {
ShaderMatSpec bind;
bind._parameter = reference;
bind._piece = SMP_whole;
bind._func = SMF_first;
bind._part[0] = SMO_vec_constant_x;
bind._arg[0] = InternalName::make(pieces[1]);
bind._part[1] = SMO_identity;
bind._arg[1] = NULL;
cp_optimize_mat_spec(bind);
_mat_spec.push_back(bind);
break;
}
case SAT_sampler1d: {
ShaderTexSpec bind;
bind._parameter = reference;
bind._name = InternalName::make(pieces[1]);
bind._desired_type=Texture::TT_1d_texture;
_tex_spec.push_back(bind);
break;
}
case SAT_sampler2d: {
ShaderTexSpec bind;
bind._parameter = reference;
bind._name = InternalName::make(pieces[1]);
bind._desired_type=Texture::TT_2d_texture;
_tex_spec.push_back(bind);
break;
}
case SAT_sampler3d: {
ShaderTexSpec bind;
bind._parameter = reference;
bind._name = InternalName::make(pieces[1]);
bind._desired_type=Texture::TT_3d_texture;
_tex_spec.push_back(bind);
break;
}
case SAT_samplercube: {
ShaderTexSpec bind;
bind._parameter = reference;
bind._name = InternalName::make(pieces[1]);
bind._desired_type = Texture::TT_cube_map;
_tex_spec.push_back(bind);
break;
}
default:
cp_report_error(p, "Invalid type for a k-parameter");
return false;
}
return true;
}
if (pieces[0] == "l") {
// IMPLEMENT THE ERROR CHECKING
return true; // Cg handles this automatically.
}
if (pieces[0] == "o") {
// IMPLEMENT THE ERROR CHECKING
return true; // Cg handles this automatically.
}
cp_report_error(p, "unrecognized parameter name");
return false;
}

View File

@ -40,156 +40,7 @@ class EXPCL_PANDA ShaderContext: public SavedContext {
public:
INLINE ShaderContext(ShaderExpansion *se);
ShaderExpansion *_shader_expansion;
public:
enum {
SHADER_type_vert=0,
SHADER_type_frag=1,
SHADER_type_both=2,
};
enum ShaderMatInput {
SMO_identity,
SMO_window_size,
SMO_pixel_size,
SMO_card_center,
SMO_mat_constant_x,
SMO_vec_constant_x,
SMO_world_to_view,
SMO_view_to_world,
SMO_model_to_view,
SMO_view_to_model,
SMO_apiview_to_view,
SMO_view_to_apiview,
SMO_clip_to_view,
SMO_view_to_clip,
SMO_apiclip_to_view,
SMO_view_to_apiclip,
SMO_view_x_to_view,
SMO_view_to_view_x,
SMO_apiview_x_to_view,
SMO_view_to_apiview_x,
SMO_clip_x_to_view,
SMO_view_to_clip_x,
SMO_apiclip_x_to_view,
SMO_view_to_apiclip_x,
};
enum ShaderArgType {
SAT_float1,
SAT_float2,
SAT_float3,
SAT_float4,
SAT_float4x4,
SAT_sampler1d,
SAT_sampler2d,
SAT_sampler3d,
SAT_samplercube,
SAT_unknown,
};
enum ShaderArgDir {
SAD_in,
SAD_out,
SAD_inout,
SAD_unknown,
};
enum ShaderMatPiece {
SMP_whole,
SMP_transpose,
SMP_row0,
SMP_row1,
SMP_row2,
SMP_row3,
SMP_col0,
SMP_col1,
SMP_col2,
SMP_col3,
};
enum ShaderMatFunc {
SMF_compose,
SMF_compose_cache_first,
SMF_compose_cache_second,
SMF_first,
};
struct ShaderMatSpec {
ShaderMatFunc _func;
ShaderMatInput _part[2];
PT(InternalName) _arg[2];
LMatrix4f _cache;
ShaderMatPiece _piece;
bool _trans_dependent;
void *_parameter;
};
struct ShaderTexSpec {
PT(InternalName) _name;
int _stage;
int _desired_type;
PT(InternalName) _suffix;
void *_parameter;
};
struct ShaderVarSpec {
PT(InternalName) _name;
int _append_uv;
void *_parameter;
};
struct ShaderArgInfo {
string _name;
ShaderArgType _type;
ShaderArgDir _direction;
bool _varying;
NotifyCategory *_cat;
};
protected:
pvector <ShaderMatSpec> _mat_spec;
pvector <ShaderTexSpec> _tex_spec;
pvector <ShaderVarSpec> _var_spec;
private:
// These functions are only called from compile_parameter.
void cp_report_error(ShaderArgInfo &arg, const string &msg);
bool cp_errchk_parameter_words(ShaderArgInfo &arg, int len);
bool cp_errchk_parameter_in(ShaderArgInfo &arg);
bool cp_errchk_parameter_varying(ShaderArgInfo &arg);
bool cp_errchk_parameter_uniform(ShaderArgInfo &arg);
bool cp_errchk_parameter_float(ShaderArgInfo &arg, int lo, int hi);
bool cp_errchk_parameter_sampler(ShaderArgInfo &arg);
bool cp_parse_trans_clause(ShaderArgInfo &arg,
ShaderMatSpec &spec,
int part,
const vector_string &pieces,
int &next,
ShaderMatInput ofop,
ShaderMatInput op);
void cp_optimize_mat_spec(ShaderMatSpec &spec);
protected:
bool compile_parameter(void *reference,
const string &arg_name,
ShaderArgType arg_type,
ShaderArgDir arg_direction,
bool arg_varying,
NotifyCategory *arg_cat);
ShaderExpansion *_expansion;
public:
static TypeHandle get_class_type() {

View File

@ -36,3 +36,69 @@ get_text() const {
return _text;
}
////////////////////////////////////////////////////////////////////
// Function: ShaderExpansion::get_header
// Access: Public
// Description: Return the ShaderExpansion's header line.
////////////////////////////////////////////////////////////////////
INLINE const string &ShaderExpansion::
get_header() const {
return _header;
}
////////////////////////////////////////////////////////////////////
// Function: ShaderExpansion::get_error_flag
// Access: Public
// Description: Returns true if the shader contains a compile-time
// error. This doesn't tell you whether or not the
// shader is supported on the current video card.
////////////////////////////////////////////////////////////////////
INLINE bool ShaderExpansion::
get_error_flag() const {
return _error_flag;
}
////////////////////////////////////////////////////////////////////
// Function: ShaderExpansion::ShaderCapabilities Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE ShaderExpansion::ShaderCaps::
ShaderCaps() {
clear();
}
////////////////////////////////////////////////////////////////////
// Function: ShaderExpansion::ShaderCapabilities::clear()
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void ShaderExpansion::ShaderCaps::
clear() {
#ifdef HAVE_CG
_active_vprofile = 0;
_active_fprofile = 0;
_ultimate_vprofile = 0;
_ultimate_fprofile = 0;
#endif
}
////////////////////////////////////////////////////////////////////
// Function: ShaderExpansion::ShaderCapabilities::operator ==
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool ShaderExpansion::ShaderCaps::
operator == (const ShaderCaps &other) const {
#ifdef HAVE_CG
if ((_active_vprofile != other._active_vprofile) ||
(_active_fprofile != other._active_fprofile) ||
(_ultimate_vprofile != other._ultimate_vprofile) ||
(_ultimate_fprofile != other._ultimate_fprofile)) {
return false;
}
#endif
return true;
}

File diff suppressed because it is too large Load Diff

View File

@ -25,29 +25,169 @@
#include "graphicsStateGuardianBase.h"
#include "internalName.h"
#ifdef HAVE_CG
// I don't want to include the Cg header file into panda as a
// whole. Instead, I'll just excerpt some opaque declarations.
typedef struct _CGcontext *CGcontext;
typedef struct _CGprogram *CGprogram;
typedef struct _CGparameter *CGparameter;
#endif
////////////////////////////////////////////////////////////////////
// Class : ShaderExpansion
// Summary: A shader can contain context-sensitive macros.
// A ShaderExpansion is the output you get when you
// run the macro preprocessor on a shader.
// The ShaderExpansion contains the shader's
// macroexpanded text, and a map of ShaderContext
// macroexpanded text, an analysis of the shader's
// parameters, and a map of ShaderContext
// objects.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA ShaderExpansion: public TypedReferenceCount {
PUBLISHED:
static PT(ShaderExpansion) make(const string &name, const string &body);
INLINE const string &get_name() const;
INLINE const string &get_text() const;
INLINE const string &get_header() const;
INLINE bool get_error_flag() const;
void prepare(PreparedGraphicsObjects *prepared_objects);
bool release(PreparedGraphicsObjects *prepared_objects);
int release_all();
PUBLISHED:
public:
enum ShaderMatInput {
SMO_identity,
SMO_window_size,
SMO_pixel_size,
SMO_card_center,
SMO_mat_constant_x,
SMO_vec_constant_x,
SMO_world_to_view,
SMO_view_to_world,
SMO_model_to_view,
SMO_view_to_model,
SMO_apiview_to_view,
SMO_view_to_apiview,
SMO_clip_to_view,
SMO_view_to_clip,
SMO_apiclip_to_view,
SMO_view_to_apiclip,
SMO_view_x_to_view,
SMO_view_to_view_x,
SMO_apiview_x_to_view,
SMO_view_to_apiview_x,
SMO_clip_x_to_view,
SMO_view_to_clip_x,
SMO_apiclip_x_to_view,
SMO_view_to_apiclip_x,
};
enum ShaderArgType {
SAT_float1,
SAT_float2,
SAT_float3,
SAT_float4,
SAT_float4x4,
SAT_sampler1d,
SAT_sampler2d,
SAT_sampler3d,
SAT_samplercube,
SAT_unknown,
};
enum ShaderArgDir {
SAD_in,
SAD_out,
SAD_inout,
SAD_unknown,
};
enum ShaderMatPiece {
SMP_whole,
SMP_transpose,
SMP_row0,
SMP_row1,
SMP_row2,
SMP_row3,
SMP_col0,
SMP_col1,
SMP_col2,
SMP_col3,
};
enum ShaderMatFunc {
SMF_compose,
SMF_compose_cache_first,
SMF_compose_cache_second,
SMF_first,
};
struct ShaderArgId {
string _name;
bool _fshader;
int _seqno;
};
struct ShaderMatSpec {
ShaderArgId _id;
ShaderMatFunc _func;
ShaderMatInput _part[2];
PT(InternalName) _arg[2];
LMatrix4f _cache;
ShaderMatPiece _piece;
bool _trans_dependent;
};
struct ShaderTexSpec {
ShaderArgId _id;
PT(InternalName) _name;
int _stage;
int _desired_type;
PT(InternalName) _suffix;
};
struct ShaderVarSpec {
ShaderArgId _id;
PT(InternalName) _name;
int _append_uv;
};
struct ShaderArgInfo {
ShaderArgId _id;
ShaderArgType _type;
ShaderArgDir _direction;
bool _varying;
NotifyCategory *_cat;
};
struct ShaderCaps {
#ifdef HAVE_CG
int _active_vprofile;
int _active_fprofile;
int _ultimate_vprofile;
int _ultimate_fprofile;
#endif;
INLINE void clear();
INLINE bool operator == (const ShaderCaps &other) const;
INLINE ShaderCaps();
};
private:
// These routines help split the shader into sections,
// for those shader implementations that need to do so.
void parse_init();
@ -57,11 +197,65 @@ PUBLISHED:
int parse_lineno();
bool parse_eof();
public:
~ShaderExpansion();
void cp_report_error(ShaderArgInfo &arg, const string &msg);
bool cp_errchk_parameter_words(ShaderArgInfo &arg, int len);
bool cp_errchk_parameter_in(ShaderArgInfo &arg);
bool cp_errchk_parameter_varying(ShaderArgInfo &arg);
bool cp_errchk_parameter_uniform(ShaderArgInfo &arg);
bool cp_errchk_parameter_float(ShaderArgInfo &arg, int lo, int hi);
bool cp_errchk_parameter_sampler(ShaderArgInfo &arg);
bool cp_parse_trans_clause(ShaderArgInfo &arg,
ShaderMatSpec &spec,
int part,
const vector_string &pieces,
int &next,
ShaderMatInput ofop,
ShaderMatInput op);
void cp_optimize_mat_spec(ShaderMatSpec &spec);
bool compile_parameter(const ShaderArgId &arg_id,
ShaderArgType arg_type,
ShaderArgDir arg_direction,
bool arg_varying,
NotifyCategory *arg_cat);
void clear_parameters();
#ifdef HAVE_CG
private:
ShaderArgType cg_parameter_type(CGparameter p);
ShaderArgDir cg_parameter_dir(CGparameter p);
CGprogram cg_compile_entry_point(char *entry, int active, int ultimate);
bool cg_analyze_entry_point(CGprogram prog, bool fshader);
bool cg_analyze_shader(const ShaderCaps &caps);
bool cg_compile_shader(const ShaderCaps &caps);
void cg_release_resources();
ShaderCaps _cg_last_caps;
CGcontext _cg_context;
CGprogram _cg_vprogram;
CGprogram _cg_fprogram;
public:
bool cg_compile_for(const ShaderCaps &caps,
CGcontext &ctx,
CGprogram &vprogram,
CGprogram &fprogram,
pvector<CGparameter> &map);
#endif
public:
pvector <ShaderMatSpec> _mat_spec;
pvector <ShaderTexSpec> _tex_spec;
pvector <ShaderVarSpec> _var_spec;
protected:
string _name;
string _text;
string _header;
bool _error_flag;
int _parse;
typedef pair < string, string > ExpansionKey;
@ -73,15 +267,23 @@ public:
typedef pmap <PreparedGraphicsObjects *, ShaderContext *> Contexts;
Contexts _contexts;
public:
ShaderContext *prepare_now(PreparedGraphicsObjects *prepared_objects,
GraphicsStateGuardianBase *gsg);
private:
ShaderExpansion();
private:
ShaderExpansion(const string &name, const string &text,
const ShaderCaps &caps);
void clear_prepared(PreparedGraphicsObjects *prepared_objects);
public:
public:
static PT(ShaderExpansion) make(const string &name, const string &body,
const ShaderCaps &caps);
~ShaderExpansion();
public:
static TypeHandle get_class_type() {
return _type_handle;
}
@ -95,7 +297,7 @@ public:
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
private:
static TypeHandle _type_handle;
};

View File

@ -44,9 +44,6 @@
#define EXPCL_GL EXPCL_PANDAMESA
#define EXPTP_GL EXPTP_PANDAMESA
#undef HAVE_CGGL // Mesa does not support Nvidia Cg... make sure it tries to compile
// without it
// Don't include Mesa's provided glext.h file; we'll provide our own
// that's more current.
#define __glext_h_

View File

@ -140,15 +140,19 @@ make(const string &body, int preprocessor) {
//
// Currently, macroexpand is just a stub that returns an
// expansion which is exactly equal to the input string.
//
// The "caps" parameter should describe the capabilities
// of the gsg on which this is intended to run.
////////////////////////////////////////////////////////////////////
PT(ShaderExpansion) Shader::
macroexpand(const RenderState *context) const {
macroexpand(const RenderState *context,
const ShaderExpansion::ShaderCaps &caps) const {
if (_fixed_expansion) {
return _fixed_expansion;
}
// I am casting away the 'const' so as to be able
// to write to this field. This field is just a cache.
((Shader*)this)->_fixed_expansion = ShaderExpansion::make(_name,_body);
((Shader*)this)->_fixed_expansion = ShaderExpansion::make(_name,_body,caps);
return _fixed_expansion;
}

View File

@ -45,7 +45,8 @@ PUBLISHED:
INLINE bool get_loaded() const;
INLINE bool get_load_error() const;
PT(ShaderExpansion) macroexpand(const RenderState *context) const;
PT(ShaderExpansion) macroexpand(const RenderState *context,
const ShaderExpansion::ShaderCaps &caps) const;
public:
Shader();