Panda3D

dxShaderContext9.cxx

00001 // Filename: dxShaderContext9.cxx
00002 // Created by: jyelon (01Sep05), conversion aignacio (Jan-Mar06)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "dxGraphicsStateGuardian9.h"
00016 #include "dxShaderContext9.h"
00017 
00018 #include <io.h>
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <fcntl.h>
00022 #include <sys/types.h>
00023 #include <sys/stat.h>
00024 #ifdef HAVE_CG
00025 #include "Cg/cgD3D9.h"
00026 #endif
00027 
00028 #define DEBUG_SHADER 0
00029 
00030 TypeHandle CLP(ShaderContext)::_type_handle;
00031 
00032 ////////////////////////////////////////////////////////////////////
00033 //     Function: DXShaderContext9::Constructor
00034 //       Access: Public
00035 //  Description: xyz
00036 ////////////////////////////////////////////////////////////////////
00037 CLP(ShaderContext)::
00038 CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) {
00039 
00040   _vertex_size = 0;
00041   _vertex_element_array = 0;
00042   _name = s->get_filename ( );
00043 
00044 #ifdef HAVE_CG
00045   _cg_context = 0;
00046   if (s->get_language() == Shader::SL_Cg) {
00047     
00048     // Ask the shader to compile itself for us and 
00049     // to give us the resulting Cg program objects.
00050 
00051     if (!s->cg_compile_for(gsg->_shader_caps,
00052                            _cg_context,
00053                            _cg_vprogram,
00054                            _cg_fprogram, 
00055                            _cg_gprogram,        // CG2 CHANGE
00056                            _cg_parameter_map)) {
00057       return;
00058     }
00059         
00060     // Load the program.
00061 
00062     BOOL paramater_shadowing;
00063     DWORD assembly_flags;
00064     
00065     paramater_shadowing = FALSE;
00066     assembly_flags = 0;
00067     
00068 #if DEBUG_SHADER
00069     assembly_flags |= D3DXSHADER_DEBUG;
00070 #endif
00071 
00072     HRESULT hr;
00073     bool success = true;
00074     hr = cgD3D9LoadProgram(_cg_vprogram, paramater_shadowing, assembly_flags);
00075     if (FAILED (hr)) {
00076       dxgsg9_cat.error()
00077         << "vertex shader cgD3D9LoadProgram failed "
00078         << D3DERRORSTRING(hr);
00079       
00080       CGerror error = cgGetError();
00081       if (error != CG_NO_ERROR) {
00082         dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
00083       }
00084       success = false;
00085     }
00086     
00087     hr = cgD3D9LoadProgram(_cg_fprogram, paramater_shadowing, assembly_flags);
00088     if (FAILED (hr)) {
00089       dxgsg9_cat.error()
00090         << "pixel shader cgD3D9LoadProgram failed "
00091         << D3DERRORSTRING(hr);
00092       
00093       CGerror error = cgGetError();
00094       if (error != CG_NO_ERROR) {
00095         dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
00096       }
00097       success = false;
00098     }    
00099 
00100     // BEGIN CG2 CHANGE
00101     if (_cg_gprogram != 0)
00102     {
00103         hr = cgD3D9LoadProgram(_cg_gprogram, paramater_shadowing, assembly_flags);
00104         if (FAILED (hr)) {
00105           dxgsg9_cat.error()
00106             << "geometry shader cgD3D9LoadProgram failed "
00107             << D3DERRORSTRING(hr);
00108 
00109           CGerror error = cgGetError();
00110           if (error != CG_NO_ERROR) {
00111             dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
00112           }
00113           success = false;
00114         }
00115     }
00116     // END CG2 CHANGE
00117 
00118     if (!success) {
00119       release_resources();
00120     }
00121   }
00122 #endif
00123 }
00124 
00125 ////////////////////////////////////////////////////////////////////
00126 //     Function: DXShaderContext9::Destructor
00127 //       Access: Public
00128 //  Description: xyz
00129 ////////////////////////////////////////////////////////////////////
00130 CLP(ShaderContext)::
00131 ~CLP(ShaderContext)() {
00132   release_resources();
00133 
00134   if (_vertex_element_array) {
00135     delete _vertex_element_array;
00136     _vertex_element_array = 0;
00137   }
00138 }
00139 
00140 // int save_file (int size, void *data, char *file_path)
00141 // {
00142 //   int state;
00143 //   int file_handle;
00144 // 
00145 //   state = false;
00146 //   file_handle = _open (file_path, _O_CREAT | _O_RDWR | _O_TRUNC, _S_IREAD | _S_IWRITE);
00147 //   if (file_handle != -1) {
00148 //     if (_write (file_handle, data, size) == size) {
00149 //       state = true;
00150 //     }
00151 //     _close (file_handle);
00152 //   }
00153 // 
00154 //   return state;
00155 // }
00156 // 
00157 //   if (dxgsg9_cat.is_debug()) {
00158 //     // DEBUG: output the generated program
00159 //     const char *vertex_program;
00160 //     const char *pixel_program;
00161 // 
00162 //     vertex_program = cgGetProgramString (_cg_program[0], CG_COMPILED_PROGRAM);
00163 //     pixel_program = cgGetProgramString (_cg_program[1], CG_COMPILED_PROGRAM);
00164 // 
00165 //     dxgsg9_cat.debug() << vertex_program << "\n";
00166 //     dxgsg9_cat.debug() << pixel_program << "\n";
00167 // 
00168 //     // save the generated program to a file
00169 //     int size;
00170 //     char file_path [512];
00171 // 
00172 //     char drive[_MAX_DRIVE];
00173 //     char dir[_MAX_DIR];
00174 //     char fname[_MAX_FNAME];
00175 //     char ext[_MAX_EXT];
00176 // 
00177 //     _splitpath (_name.c_str ( ), drive, dir, fname, ext);
00178 // 
00179 //     size = strlen (vertex_program);
00180 //     sprintf (file_path, "%s.vasm", fname);
00181 //     save_file (size, (void *) vertex_program, file_path);
00182 // 
00183 //     size = strlen (pixel_program);
00184 //     sprintf (file_path, "%s.pasm", fname);
00185 //     save_file (size, (void *) pixel_program, file_path);
00186 //   }
00187 
00188 ////////////////////////////////////////////////////////////////////
00189 //     Function: DXShaderContext9::release_resources
00190 //       Access: Public
00191 //  Description: Should deallocate all system resources (such as
00192 //               vertex program handles or Cg contexts).
00193 ////////////////////////////////////////////////////////////////////
00194 void CLP(ShaderContext)::
00195 release_resources() {
00196 #ifdef HAVE_CG
00197   if (_cg_context) {
00198     cgDestroyContext(_cg_context);
00199     _cg_context = 0;
00200     _cg_vprogram = 0;
00201     _cg_fprogram = 0;
00202     _cg_gprogram = 0;   // CG2 CHANGE
00203     _cg_parameter_map.clear();
00204   }
00205 #endif
00206 }
00207 
00208 ////////////////////////////////////////////////////////////////////
00209 //     Function: DXShaderContext9::bind
00210 //       Access: Public
00211 //  Description: This function is to be called to enable a new
00212 //               shader.  It also initializes all of the shader's
00213 //               input parameters.
00214 ////////////////////////////////////////////////////////////////////
00215 bool CLP(ShaderContext)::
00216 bind(GSG *gsg) {
00217 
00218   bool bind_state;
00219 
00220   bind_state = false;
00221 #ifdef HAVE_CG
00222   if (_cg_context) {
00223     // clear the last cached FVF to make sure the next SetFVF call goes through
00224                                                            
00225     gsg -> _last_fvf = 0;
00226 
00227     // Pass in k-parameters and transform-parameters
00228     issue_parameters(gsg, Shader::SSD_general);
00229     
00230     HRESULT hr;
00231     
00232     // Bind the shaders.
00233     bind_state = true;
00234     hr = cgD3D9BindProgram(_cg_vprogram);
00235     if (FAILED (hr)) {
00236       dxgsg9_cat.error() << "cgD3D9BindProgram vertex shader failed " << D3DERRORSTRING(hr);
00237       
00238       CGerror error = cgGetError();
00239       if (error != CG_NO_ERROR) {
00240         dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
00241       }
00242       
00243       bind_state = false;
00244     }
00245     hr = cgD3D9BindProgram(_cg_fprogram);
00246     if (FAILED (hr)) {
00247       dxgsg9_cat.error() << "cgD3D9BindProgram pixel shader failed " << D3DERRORSTRING(hr);
00248       
00249       CGerror error = cgGetError();
00250       if (error != CG_NO_ERROR) {
00251         dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
00252       }
00253       
00254       bind_state = false;
00255     }
00256 
00257     // BEGIN CG2 CHANGE
00258     if (_cg_gprogram != 0)
00259     {
00260         hr = cgD3D9BindProgram(_cg_gprogram);
00261         if (FAILED (hr)) {
00262           dxgsg9_cat.error() << "cgD3D9BindProgram geometry shader failed " << D3DERRORSTRING(hr);
00263 
00264           CGerror error = cgGetError();
00265           if (error != CG_NO_ERROR) {
00266             dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
00267           }
00268 
00269           bind_state = false;
00270         }
00271     }
00272     // END CG2 CHANGE
00273   }
00274 #endif
00275 
00276   return bind_state;
00277 }
00278 
00279 ////////////////////////////////////////////////////////////////////
00280 //     Function: DXShaderContext9::unbind
00281 //       Access: Public
00282 //  Description: This function disables a currently-bound shader.
00283 ////////////////////////////////////////////////////////////////////
00284 void CLP(ShaderContext)::
00285 unbind(GSG *gsg) {
00286 
00287 #ifdef HAVE_CG
00288   if (_cg_context) {
00289     HRESULT hr;
00290 
00291     hr = gsg -> _d3d_device -> SetVertexShader (NULL);
00292     if (FAILED (hr)) {
00293       dxgsg9_cat.error()
00294         << "SetVertexShader (NULL) failed " << D3DERRORSTRING(hr);
00295     }
00296     hr = gsg -> _d3d_device -> SetPixelShader (NULL);
00297     if (FAILED (hr)) {
00298       dxgsg9_cat.error()
00299         << "SetPixelShader (NULL) failed " << D3DERRORSTRING(hr);
00300     }
00301   }
00302 #endif
00303 }
00304 
00305 ////////////////////////////////////////////////////////////////////
00306 //     Function: DXShaderContext9::issue_parameters
00307 //       Access: Public
00308 //  Description: This function gets called whenever the RenderState
00309 //               or TransformState has changed, but the Shader
00310 //               itself has not changed.  It loads new values into the
00311 //               shader's parameters.
00312 //
00313 //               If "altered" is false, that means you promise that
00314 //               the parameters for this shader context have already
00315 //               been issued once, and that since the last time the
00316 //               parameters were issued, no part of the render
00317 //               state has changed except the external and internal
00318 //               transforms.
00319 ////////////////////////////////////////////////////////////////////
00320 
00321 #if DEBUG_SHADER
00322 float *global_data = 0;
00323 ShaderContext::ShaderMatSpec *global_shader_mat_spec = 0;
00324 InternalName *global_internal_name_0 = 0;
00325 InternalName *global_internal_name_1 = 0;
00326 #endif
00327 
00328 void CLP(ShaderContext)::
00329 issue_parameters(GSG *gsg, int altered)
00330 {
00331 #ifdef HAVE_CG
00332   if (_cg_context) {
00333     for (int i=0; i<(int)_shader->_mat_spec.size(); i++) {
00334       if (altered & (_shader->_mat_spec[i]._dep[0] | _shader->_mat_spec[i]._dep[1])) {
00335         CGparameter p = _cg_parameter_map[_shader->_mat_spec[i]._id._seqno];
00336         if (p == NULL) {
00337           continue;
00338         }        
00339         const LMatrix4f *val = gsg->fetch_specified_value(_shader->_mat_spec[i], altered);
00340         if (val) {
00341           HRESULT hr;
00342           float v [4];
00343           LMatrix4f temp_matrix;
00344 
00345           hr = D3D_OK;
00346 
00347           const float *data;
00348 
00349           data = val -> get_data ( );
00350 
00351           #if DEBUG_SHADER
00352           // DEBUG
00353           global_data = (float *) data;
00354           global_shader_mat_spec = &_shader->_mat_spec[i];
00355           global_internal_name_0 = global_shader_mat_spec -> _arg [0];
00356           global_internal_name_1 = global_shader_mat_spec -> _arg [1];
00357           #endif
00358 
00359           switch (_shader->_mat_spec[i]._piece) {
00360           case Shader::SMP_whole:
00361             // TRANSPOSE REQUIRED
00362             temp_matrix.transpose_from (*val);
00363             data = temp_matrix.get_data();
00364 
00365             hr = cgD3D9SetUniform (p, data);
00366             break;
00367 
00368           case Shader::SMP_transpose:
00369             // NO TRANSPOSE REQUIRED
00370             hr = cgD3D9SetUniform (p, data);
00371             break;
00372 
00373           case Shader::SMP_row0:
00374             hr = cgD3D9SetUniform (p, data + 0);
00375             break;
00376           case Shader::SMP_row1:
00377             hr = cgD3D9SetUniform (p, data + 4);
00378             break;
00379           case Shader::SMP_row2:
00380             hr = cgD3D9SetUniform (p, data + 8);
00381             break;
00382           case Shader::SMP_row3x1:
00383           case Shader::SMP_row3x2:
00384           case Shader::SMP_row3x3:
00385           case Shader::SMP_row3:
00386             hr = cgD3D9SetUniform (p, data + 12);
00387             break;
00388 
00389           case Shader::SMP_col0:
00390             v[0] = data[0]; v[1] = data[4]; v[2] = data[8]; v[3] = data[12];
00391             hr = cgD3D9SetUniform (p, v);
00392             break;
00393           case Shader::SMP_col1:
00394             v[0] = data[1]; v[1] = data[5]; v[2] = data[9]; v[3] = data[13];
00395             hr = cgD3D9SetUniform (p, v);
00396             break;
00397           case Shader::SMP_col2:
00398             v[0] = data[2]; v[1] = data[6]; v[2] = data[10]; v[3] = data[14];
00399             hr = cgD3D9SetUniform (p, v);
00400             break;
00401           case Shader::SMP_col3:
00402             v[0] = data[3]; v[1] = data[7]; v[2] = data[11]; v[3] = data[15];
00403             hr = cgD3D9SetUniform (p, v);
00404             break;
00405 
00406           default:
00407             dxgsg9_cat.error()
00408               << "issue_parameters ( ) SMP parameter type not implemented " << _shader->_mat_spec[i]._piece << "\n";
00409             break;
00410           }
00411 
00412           if (FAILED (hr)) {
00413 
00414             string name = "unnamed";
00415 
00416             if (_shader->_mat_spec[i]._arg [0]) {
00417               name = _shader->_mat_spec[i]._arg [0] -> get_basename ( );
00418             }
00419 
00420             dxgsg9_cat.error()
00421               << "NAME  " << name << "\n"
00422               << "MAT TYPE  "
00423               << _shader->_mat_spec[i]._piece
00424               << " cgD3D9SetUniform failed "
00425               << D3DERRORSTRING(hr);
00426 
00427             CGerror error = cgGetError ();
00428             if (error != CG_NO_ERROR) {
00429               dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
00430             }
00431           }
00432         }
00433       }
00434     }
00435   }
00436 #endif
00437 }
00438 
00439 ////////////////////////////////////////////////////////////////////
00440 //     Function: DXShaderContext9::disable_shader_vertex_arrays
00441 //       Access: Public
00442 //  Description: Disable all the vertex arrays used by this shader.
00443 ////////////////////////////////////////////////////////////////////
00444 void CLP(ShaderContext)::
00445 disable_shader_vertex_arrays(GSG *gsg)
00446 {
00447 #ifdef HAVE_CG
00448   if (_cg_context) {
00449     // DO NOTHING, CURRENTLY USING ONLY ONE STREAM SOURCE
00450   }
00451 #endif
00452 }
00453 
00454 ////////////////////////////////////////////////////////////////////
00455 //     Function: DXShaderContext9::update_shader_vertex_arrays
00456 //       Access: Public
00457 //  Description: Disables all vertex arrays used by the previous
00458 //               shader, then enables all the vertex arrays needed
00459 //               by this shader.  Extracts the relevant vertex array
00460 //               data from the gsg.
00461 //               The current implementation is inefficient, because
00462 //               it may unnecessarily disable arrays then immediately
00463 //               reenable them.  We may optimize this someday.
00464 ////////////////////////////////////////////////////////////////////
00465 
00466 // DEBUG
00467 #if DEBUG_SHADER
00468 VertexElementArray *global_vertex_element_array = 0;
00469 #endif
00470 
00471 void CLP(ShaderContext)::
00472 update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
00473 {
00474   if (prev) prev->disable_shader_vertex_arrays(gsg);
00475 #ifdef HAVE_CG
00476   if (_cg_context) {
00477 
00478   #ifdef SUPPORT_IMMEDIATE_MODE
00479 /*
00480     if (gsg->_use_sender) {
00481       dxgsg9_cat.error() << "immediate mode shaders not implemented yet\n";
00482     } else
00483 */
00484   #endif // SUPPORT_IMMEDIATE_MODE
00485     {
00486       if (_vertex_element_array == 0) {
00487         bool error;
00488         const GeomVertexArrayDataHandle *array_reader;
00489         Geom::NumericType numeric_type;
00490         int start, stride, num_values;
00491         int nvarying = _shader->_var_spec.size();
00492 
00493         int stream_index;
00494         VertexElementArray *vertex_element_array;
00495 
00496         error = false;
00497         // SHADER ISSUE: STREAM INDEX ALWAYS 0 FOR VERTEX BUFFER?
00498         stream_index = 0;
00499         vertex_element_array = new VertexElementArray (nvarying + 2);
00500 
00501         #if DEBUG_SHADER
00502         // DEBUG
00503         global_vertex_element_array = vertex_element_array;
00504         #endif
00505 
00506         for (int i=0; i<nvarying; i++) {
00507           CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno];
00508           if (p == NULL) {
00509             continue;
00510           }        
00511           InternalName *name = _shader->_var_spec[i]._name;
00512           int texslot = _shader->_var_spec[i]._append_uv;
00513           if (texslot >= 0 && texslot < gsg->_state_texture->get_num_on_stages()) {
00514             TextureStage *stage = gsg->_state_texture->get_on_stage(texslot);
00515             InternalName *texname = stage->get_texcoord_name();
00516             if (name == InternalName::get_texcoord()) {
00517               name = texname;
00518             } else if (texname != InternalName::get_texcoord()) {
00519               name = name->append(texname->get_basename());
00520             }
00521           }
00522           if (gsg->_data_reader->get_array_info(name, array_reader, num_values, numeric_type, start, stride)) {
00523 
00524             if (false) {
00525 
00526             } else if (name -> get_top ( ) == InternalName::get_vertex ( )) {
00527 
00528               if (numeric_type == Geom::NT_float32) {
00529                 switch (num_values) {
00530                   case 3:
00531                     vertex_element_array -> add_position_xyz_vertex_element (stream_index);
00532                     break;
00533                   case 4:
00534                     vertex_element_array -> add_position_xyzw_vertex_element (stream_index);
00535                     break;
00536                   default:
00537                     dxgsg9_cat.error ( ) << "VE ERROR: invalid number of vertex coordinate elements " << num_values << "\n";
00538                     break;
00539                 }
00540               } else {
00541                 dxgsg9_cat.error ( ) << "VE ERROR: invalid vertex type " << numeric_type << "\n";
00542               }
00543 
00544             } else if (name -> get_top ( ) == InternalName::get_texcoord ( )) {
00545 
00546               if (numeric_type == Geom::NT_float32) {
00547                 switch (num_values)
00548                 {
00549                   case 1:
00550                     vertex_element_array -> add_u_vertex_element (stream_index);
00551                     break;
00552                   case 2:
00553                     vertex_element_array -> add_uv_vertex_element (stream_index);
00554                     break;
00555                   case 3:
00556                     vertex_element_array -> add_uvw_vertex_element (stream_index);
00557                     break;
00558                   default:
00559                     dxgsg9_cat.error ( ) << "VE ERROR: invalid number of vertex texture coordinate elements " << num_values <<  "\n";
00560                     break;
00561                 }
00562               } else {
00563                 dxgsg9_cat.error ( ) << "VE ERROR: invalid texture coordinate type " << numeric_type << "\n";
00564               }
00565 
00566             } else if (name -> get_top ( ) == InternalName::get_normal ( )) {
00567 
00568               if (numeric_type == Geom::NT_float32) {
00569                 switch (num_values)
00570                 {
00571                   case 3:
00572                     vertex_element_array -> add_normal_vertex_element (stream_index);
00573                     break;
00574                   default:
00575                     dxgsg9_cat.error ( ) << "VE ERROR: invalid number of normal coordinate elements " << num_values << "\n";
00576                     break;
00577                 }
00578               } else {
00579                 dxgsg9_cat.error ( ) << "VE ERROR: invalid normal type " << numeric_type << "\n";
00580               }
00581 
00582             } else if (name -> get_top ( ) == InternalName::get_binormal ( )) {
00583 
00584               if (numeric_type == Geom::NT_float32) {
00585                 switch (num_values)
00586                 {
00587                   case 3:
00588                     vertex_element_array -> add_binormal_vertex_element (stream_index);
00589                     break;
00590                   default:
00591                     dxgsg9_cat.error ( ) << "VE ERROR: invalid number of binormal coordinate elements " << num_values << "\n";
00592                     break;
00593                 }
00594               } else {
00595                 dxgsg9_cat.error ( ) << "VE ERROR: invalid binormal type " << numeric_type << "\n";
00596               }
00597 
00598             } else if (name -> get_top ( ) == InternalName::get_tangent ( )) {
00599 
00600               if (numeric_type == Geom::NT_float32) {
00601                 switch (num_values)
00602                 {
00603                   case 3:
00604                     vertex_element_array -> add_tangent_vertex_element (stream_index);
00605                     break;
00606                   default:
00607                     dxgsg9_cat.error ( ) << "VE ERROR: invalid number of tangent coordinate elements " << num_values << "\n";
00608                     break;
00609                 }
00610               } else {
00611                 dxgsg9_cat.error ( ) << "VE ERROR: invalid tangent type " << numeric_type << "\n";
00612               }
00613 
00614             } else if (name -> get_top ( ) == InternalName::get_color ( )) {
00615 
00616               if (numeric_type == Geom::NT_packed_dcba ||
00617                   numeric_type == Geom::NT_packed_dabc ||
00618                   numeric_type == Geom::NT_uint8) {
00619                 switch (num_values)
00620                 {
00621                   case 4:
00622                     vertex_element_array -> add_diffuse_color_vertex_element (stream_index);
00623                     break;
00624                   default:
00625                     dxgsg9_cat.error ( ) << "VE ERROR: invalid color coordinates " << num_values << "\n";
00626                     break;
00627                 }
00628               } else {
00629                 dxgsg9_cat.error ( ) << "VE ERROR: invalid color type " << numeric_type << "\n";
00630               }
00631 
00632             } else {
00633               dxgsg9_cat.error ( ) << "VE ERROR: unsupported vertex element " << name -> get_name ( ) << "\n";
00634             }
00635 
00636           } else {
00637             dxgsg9_cat.error ( )
00638               << "get_array_info ( ) failed for shader "
00639               << _name
00640               << "\n"
00641               << "  vertex element name = "
00642               << name -> get_name ( )
00643               << "\n";
00644             error = true;
00645           }
00646         }
00647 
00648         if (error) {
00649           delete vertex_element_array;
00650         }
00651         else {
00652           int state;
00653 
00654           state = vertex_element_array -> add_end_vertex_element ( );
00655           if (state) {
00656             if (_cg_context) {
00657               if (cgD3D9ValidateVertexDeclaration (_cg_vprogram,
00658                     vertex_element_array -> vertex_element_array) == CG_TRUE) {
00659                 dxgsg9_cat.debug() << "|||||cgD3D9ValidateVertexDeclaration succeeded\n";
00660               }
00661               else {
00662               }
00663             }
00664             else {
00665 
00666             }
00667 
00668             _vertex_size = vertex_element_array -> offset;
00669             _vertex_element_array = vertex_element_array;
00670           }
00671           else {
00672             dxgsg9_cat.error ( ) << "VertexElementArray creation failed\n";
00673             delete vertex_element_array;
00674           }
00675         }
00676       }
00677     }
00678   }
00679 #endif // HAVE_CG
00680 }
00681 
00682 ////////////////////////////////////////////////////////////////////
00683 //     Function: DXShaderContext9::disable_shader_texture_bindings
00684 //       Access: Public
00685 //  Description: Disable all the texture bindings used by this shader.
00686 ////////////////////////////////////////////////////////////////////
00687 void CLP(ShaderContext)::
00688 disable_shader_texture_bindings(GSG *gsg)
00689 {
00690 #ifdef HAVE_CG
00691   if (_cg_context) {
00692     for (int i=0; i<(int)_shader->_tex_spec.size(); i++) {
00693       CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno];
00694       if (p == NULL) {
00695         continue;
00696       }        
00697       int texunit = cgGetParameterResourceIndex(p);
00698 
00699       HRESULT hr;
00700 
00701       hr = gsg -> _d3d_device -> SetTexture (texunit, NULL);
00702       if (FAILED (hr)) {
00703         dxgsg9_cat.error()
00704           << "SetTexture ("
00705           << texunit
00706           << ", NULL) failed "
00707           << D3DERRORSTRING(hr);
00708       }
00709     }
00710   }
00711 #endif
00712 }
00713 
00714 ////////////////////////////////////////////////////////////////////
00715 //     Function: DXShaderContext9::update_shader_texture_bindings
00716 //       Access: Public
00717 //  Description: Disables all texture bindings used by the previous
00718 //               shader, then enables all the texture bindings needed
00719 //               by this shader.  Extracts the relevant vertex array
00720 //               data from the gsg.
00721 //               The current implementation is inefficient, because
00722 //               it may unnecessarily disable textures then immediately
00723 //               reenable them.  We may optimize this someday.
00724 ////////////////////////////////////////////////////////////////////
00725 void CLP(ShaderContext)::
00726 update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg)
00727 {
00728   if (prev) prev->disable_shader_texture_bindings(gsg);
00729 
00730 #ifdef HAVE_CG
00731   if (_cg_context) {
00732 
00733     for (int i=0; i<(int)_shader->_tex_spec.size(); i++) {
00734       CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno];
00735       if (p == NULL) {
00736         continue;
00737       }        
00738       Texture *tex = 0;
00739       InternalName *id = _shader->_tex_spec[i]._name;
00740       if (id != 0) {
00741         const ShaderInput *input = gsg->_target_shader->get_shader_input(id);
00742         tex = input->get_texture();
00743       } else {
00744         // We get the TextureAttrib directly from the _target_rs, not the
00745         // filtered TextureAttrib in _target_texture.
00746         const TextureAttrib *texattrib = DCAST(TextureAttrib, gsg->_target_rs->get_attrib_def(TextureAttrib::get_class_slot()));
00747         nassertv(texattrib != (TextureAttrib *)NULL);
00748 
00749         if (_shader->_tex_spec[i]._stage >= texattrib->get_num_on_stages()) {
00750           continue;
00751         }
00752         TextureStage *stage = texattrib->get_on_stage(_shader->_tex_spec[i]._stage);
00753         tex = texattrib->get_on_texture(stage);
00754       }
00755       if (_shader->_tex_spec[i]._suffix != 0) {
00756         // The suffix feature is inefficient. It is a temporary hack.
00757         if (tex == 0) {
00758           continue;
00759         }
00760         tex = tex->load_related(_shader->_tex_spec[i]._suffix);
00761       }
00762       if ((tex == 0) || (tex->get_texture_type() != _shader->_tex_spec[i]._desired_type)) {
00763         continue;
00764       }
00765       TextureContext *tc = tex->prepare_now(gsg->_prepared_objects, gsg);
00766       //      TextureContext *tc = tex->prepare_now(gsg->get_prepared_objects(), gsg);
00767       if (tc == (TextureContext*)NULL) {
00768         continue;
00769       }
00770       
00771       int texunit = cgGetParameterResourceIndex(p);
00772       
00773       gsg->apply_texture(texunit, tc);
00774     }
00775   }
00776 #endif
00777 }
00778 
00779 // DEBUG CODE TO TEST ASM CODE GENERATED BY Cg
00780 void assemble_shader_test(char *file_path)
00781 {
00782   int flags;
00783   D3DXMACRO *defines;
00784   LPD3DXINCLUDE include;
00785   LPD3DXBUFFER shader;
00786   LPD3DXBUFFER error_messages;
00787 
00788   flags = 0;
00789   defines = 0;
00790   include = 0;
00791   shader = 0;
00792   error_messages = 0;
00793 
00794   D3DXAssembleShaderFromFile (file_path, defines, include, flags, &shader, &error_messages);
00795   if (error_messages)
00796   {
00797     char *error_message;
00798 
00799     error_message = (char *) (error_messages -> GetBufferPointer ( ));
00800     if (error_message)
00801     {
00802       dxgsg9_cat.error() << error_message;
00803     }
00804 
00805     error_messages -> Release ( );
00806   }
00807 }
 All Classes Functions Variables Enumerations