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