Panda3D

dxVertexBufferContext9.cxx

00001 // Filename: dxVertexBufferContext9.cxx
00002 // Created by:  drose (18Mar05)
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 "dxVertexBufferContext9.h"
00016 #include "geomVertexArrayData.h"
00017 #include "geomVertexArrayFormat.h"
00018 #include "graphicsStateGuardian.h"
00019 #include "pStatTimer.h"
00020 #include "internalName.h"
00021 #include "config_dxgsg9.h"
00022 
00023 #define DEBUG_VERTEX_BUFFER false
00024 
00025 TypeHandle DXVertexBufferContext9::_type_handle;
00026 
00027 ////////////////////////////////////////////////////////////////////
00028 //     Function: DXVertexBufferContext9::Constructor
00029 //       Access: Public
00030 //  Description:
00031 ////////////////////////////////////////////////////////////////////
00032 DXVertexBufferContext9::
00033 DXVertexBufferContext9(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data, DXScreenData &scrn) :
00034   VertexBufferContext(pgo, data),
00035   _vbuffer(NULL)
00036 {
00037   // Now fill in the FVF code.
00038   const GeomVertexArrayFormat *array_format = data->get_array_format();
00039 
00040   // We have to start with the vertex data, and work up from there in
00041   // order, since that's the way the FVF is defined.
00042   int index;
00043   int n = 0;
00044   int num_columns = array_format->get_num_columns();
00045 
00046   _vertex_element_type_array = 0;
00047 
00048   VERTEX_ELEMENT_TYPE *vertex_element_type_array;
00049 
00050 //  if (scrn._dxgsg9 -> _current_shader_context)
00051   {
00052     int total_elements;
00053     unsigned char vertex_element_type_counter_array [VS_TOTAL_TYPES];
00054     VERTEX_ELEMENT_TYPE *vertex_element_type;
00055 
00056     total_elements = num_columns + 2;
00057     vertex_element_type_array = new VERTEX_ELEMENT_TYPE [total_elements];
00058     memset (vertex_element_type_array, 0, total_elements * sizeof (VERTEX_ELEMENT_TYPE));
00059     memset (vertex_element_type_counter_array, 0, sizeof (vertex_element_type_counter_array));
00060 
00061     // create a simple vertex type mapping from the vertex elements
00062     vertex_element_type = vertex_element_type_array;
00063     for (index = 0; index < num_columns; index++)
00064     {
00065       int num_values;
00066       const InternalName *name;
00067 
00068       name = array_format -> get_column (index) -> get_name ( );
00069       num_values = array_format -> get_column(index) -> get_num_values ( );
00070 
00071       if (false) {
00072 
00073       } else if (name -> get_top ( ) == InternalName::get_vertex ( )) {
00074 
00075         switch (num_values)
00076         {
00077           case 3:
00078             vertex_element_type -> vs_input_type = VS_POSITION_XYZ;
00079             break;
00080           case 4:
00081             vertex_element_type -> vs_input_type = VS_POSITION_XYZW;
00082             break;
00083           default:
00084             dxgsg9_cat.warning ( ) << "VERTEX ERROR: invalid number of position coordinate elements " << num_values << "\n";
00085             break;
00086         }
00087 
00088       } else if (name -> get_top ( ) == InternalName::get_texcoord ( )) {
00089 
00090         switch (num_values)
00091         {
00092           case 1:
00093             vertex_element_type -> vs_input_type = VS_TEXTURE_U;
00094             break;
00095           case 2:
00096             vertex_element_type -> vs_input_type = VS_TEXTURE_UV;
00097             break;
00098           case 3:
00099             vertex_element_type -> vs_input_type = VS_TEXTURE_UVW;
00100             break;
00101           default:
00102             dxgsg9_cat.warning ( ) << "VERTEX ERROR: invalid number of vertex texture coordinate elements " << num_values << "\n";
00103             break;
00104         }
00105 
00106       } else if (name -> get_top ( ) == InternalName::get_normal ( )) {
00107 
00108         vertex_element_type -> vs_input_type = VS_NORMAL;
00109 
00110       } else if (name -> get_top ( ) == InternalName::get_binormal ( )) {
00111 
00112         vertex_element_type -> vs_input_type = VS_BINORMAL;
00113 
00114       } else if (name -> get_top ( ) == InternalName::get_tangent ( )) {
00115 
00116         vertex_element_type -> vs_input_type = VS_TANGENT;
00117 
00118       } else if (name -> get_top ( ) == InternalName::get_color ( )) {
00119 
00120         vertex_element_type -> vs_input_type = VS_DIFFUSE;
00121 
00122       } else {
00123 
00124         dxgsg9_cat.error ( )
00125           << "VERTEX ERROR: unsupported vertex element " << name -> get_name ( )
00126           << "\n";
00127 
00128         vertex_element_type -> vs_input_type = VS_ERROR;
00129       }
00130 
00131       vertex_element_type -> index = vertex_element_type_counter_array [vertex_element_type -> vs_input_type];
00132       vertex_element_type_counter_array [vertex_element_type -> vs_input_type]++;
00133 
00134       // SHADER ISSUE: STREAM INDEX ALWAYS 0 FOR VERTEX BUFFER ???
00135       vertex_element_type -> stream = 0;
00136       vertex_element_type -> offset = array_format -> get_column(index) -> get_start ( );
00137 
00138       vertex_element_type++;
00139     }
00140   }
00141 
00142   _vertex_element_type_array = vertex_element_type_array;
00143 
00144   _fvf = 0;
00145   _managed = -1;
00146 
00147   _direct_3d_vertex_declaration = 0;
00148   _shader_context = 0;
00149 
00150   if (n < num_columns &&
00151       array_format->get_column(n)->get_name() == InternalName::get_vertex()) {
00152     ++n;
00153 
00154     int num_blend_values = 0;
00155 
00156     if (n < num_columns &&
00157         array_format->get_column(n)->get_name() == InternalName::get_transform_weight()) {
00158       // We have hardware vertex animation.
00159       num_blend_values = array_format->get_column(n)->get_num_values();
00160       ++n;
00161     }
00162 
00163     if (n < num_columns &&
00164         array_format->get_column(n)->get_name() == InternalName::get_transform_index()) {
00165       // Furthermore, it's indexed vertex animation.
00166       _fvf |= D3DFVF_LASTBETA_UBYTE4;
00167       ++num_blend_values;
00168       ++n;
00169     }
00170 
00171     switch (num_blend_values) {
00172     case 0:
00173       _fvf |= D3DFVF_XYZ;
00174       break;
00175 
00176     case 1:
00177       _fvf |= D3DFVF_XYZB1;
00178       break;
00179 
00180     case 2:
00181       _fvf |= D3DFVF_XYZB2;
00182       break;
00183 
00184     case 3:
00185       _fvf |= D3DFVF_XYZB3;
00186       break;
00187 
00188     case 4:
00189       _fvf |= D3DFVF_XYZB4;
00190       break;
00191 
00192     case 5:
00193       _fvf |= D3DFVF_XYZB5;
00194       break;
00195     }
00196   }
00197 
00198   if (n < num_columns &&
00199       array_format->get_column(n)->get_name() == InternalName::get_normal()) {
00200     _fvf |= D3DFVF_NORMAL;
00201     ++n;
00202   }
00203   if (n < num_columns &&
00204       array_format->get_column(n)->get_name() == InternalName::get_color()) {
00205     _fvf |= D3DFVF_DIFFUSE;
00206     ++n;
00207   }
00208 
00209   // Now look for all of the texcoord names and enable them in the
00210   // same order they appear in the array.
00211   int texcoord_index = 0;
00212   while (n < num_columns &&
00213          array_format->get_column(n)->get_contents() == Geom::C_texcoord) {
00214     const GeomVertexColumn *column = array_format->get_column(n);
00215     switch (column->get_num_values()) {
00216     case 1:
00217       _fvf |= D3DFVF_TEXCOORDSIZE1(texcoord_index);
00218       ++n;
00219       break;
00220     case 2:
00221       _fvf |= D3DFVF_TEXCOORDSIZE2(texcoord_index);
00222       ++n;
00223       break;
00224     case 3:
00225       _fvf |= D3DFVF_TEXCOORDSIZE3(texcoord_index);
00226       ++n;
00227       break;
00228     case 4:
00229       _fvf |= D3DFVF_TEXCOORDSIZE4(texcoord_index);
00230       ++n;
00231       break;
00232     }
00233     ++texcoord_index;
00234   }
00235 
00236   switch (texcoord_index) {
00237   case 0:
00238     break;
00239   case 1:
00240     _fvf |= D3DFVF_TEX1;
00241     break;
00242   case 2:
00243     _fvf |= D3DFVF_TEX2;
00244     break;
00245   case 3:
00246     _fvf |= D3DFVF_TEX3;
00247     break;
00248   case 4:
00249     _fvf |= D3DFVF_TEX4;
00250     break;
00251   case 5:
00252     _fvf |= D3DFVF_TEX5;
00253     break;
00254   case 6:
00255     _fvf |= D3DFVF_TEX6;
00256     break;
00257   case 7:
00258     _fvf |= D3DFVF_TEX7;
00259     break;
00260   case 8:
00261     _fvf |= D3DFVF_TEX8;
00262     break;
00263   }
00264 }
00265 
00266 ////////////////////////////////////////////////////////////////////
00267 //     Function: DXVertexBufferContext9::Destructor
00268 //       Access: Public
00269 //  Description:
00270 ////////////////////////////////////////////////////////////////////
00271 DXVertexBufferContext9::
00272 ~DXVertexBufferContext9() {
00273 
00274   if (_vertex_element_type_array) {
00275     delete _vertex_element_type_array;
00276     _vertex_element_type_array = 0;
00277   }
00278   if (_direct_3d_vertex_declaration) {
00279     _direct_3d_vertex_declaration -> Release ( );
00280     _direct_3d_vertex_declaration = 0;
00281   }
00282 
00283   free_vbuffer ( );
00284 }
00285 
00286 ////////////////////////////////////////////////////////////////////
00287 //     Function: DXVertexBufferContext9::evict_lru
00288 //       Access: Public, Virtual
00289 //  Description: Evicts the page from the LRU.  Called internally when
00290 //               the LRU determines that it is full.  May also be
00291 //               called externally when necessary to explicitly evict
00292 //               the page.
00293 //
00294 //               It is legal for this method to either evict the page
00295 //               as requested, do nothing (in which case the eviction
00296 //               will be requested again at the next epoch), or
00297 //               requeue itself on the tail of the queue (in which
00298 //               case the eviction will be requested again much
00299 //               later).
00300 ////////////////////////////////////////////////////////////////////
00301 void DXVertexBufferContext9::
00302 evict_lru() {
00303   dequeue_lru();
00304   free_vbuffer();
00305   update_data_size_bytes(0);
00306   mark_unloaded();
00307 }
00308 
00309 ////////////////////////////////////////////////////////////////////
00310 //     Function: DXVertexBufferContext9::free_vbuffer
00311 //       Access: Public
00312 //  Description: Frees vertex buffer memory.
00313 ////////////////////////////////////////////////////////////////////
00314 void DXVertexBufferContext9::
00315 free_vbuffer(void) {
00316 
00317   if (_vbuffer != NULL) {
00318     if (DEBUG_VERTEX_BUFFER && dxgsg9_cat.is_debug()) {
00319       dxgsg9_cat.debug()
00320         << "deleting vertex buffer " << _vbuffer << "\n";
00321     }
00322 
00323     if (DEBUG_VERTEX_BUFFER) {
00324       RELEASE(_vbuffer, dxgsg9, "vertex buffer", RELEASE_ONCE);
00325     }
00326     else {
00327       _vbuffer -> Release ( );
00328     }
00329 
00330     _vbuffer = NULL;
00331   }
00332 }
00333 
00334 ////////////////////////////////////////////////////////////////////
00335 //     Function: DXVertexBufferContext9::allocate_vbuffer
00336 //       Access: Public
00337 //  Description: Allocates vertex buffer memory.
00338 ////////////////////////////////////////////////////////////////////
00339 void DXVertexBufferContext9::
00340 allocate_vbuffer(DXScreenData &scrn,
00341                  const GeomVertexArrayDataHandle *reader) {
00342 
00343   int data_size;
00344   HRESULT hr;
00345   DWORD usage;
00346   D3DPOOL pool;
00347 
00348   data_size = reader->get_data_size_bytes();
00349 
00350   _managed = scrn._managed_vertex_buffers;
00351   if (_managed) {
00352     pool = D3DPOOL_MANAGED;
00353     usage = D3DUSAGE_WRITEONLY;
00354   }
00355   else {
00356     pool = D3DPOOL_DEFAULT;
00357     usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC;
00358   }
00359 
00360   int attempts;
00361 
00362   attempts = 0;
00363   do
00364   {
00365     hr = scrn._d3d_device->CreateVertexBuffer
00366         (data_size, usage, _fvf, pool, &_vbuffer, NULL);
00367     attempts++;
00368   }
00369   while (scrn._dxgsg9 -> check_dx_allocation (hr, data_size, attempts));
00370 
00371   if (FAILED(hr)) {
00372     dxgsg9_cat.warning()
00373       << "CreateVertexBuffer failed" << D3DERRORSTRING(hr);
00374       
00375     printf ("data_size %d \n", data_size);
00376     
00377     _vbuffer = NULL;
00378   } else {
00379     if (DEBUG_VERTEX_BUFFER && dxgsg9_cat.is_debug()) {
00380       dxgsg9_cat.debug()
00381         << "created vertex buffer " << _vbuffer << ": "
00382         << reader->get_num_rows() << " vertices "
00383         << *reader->get_array_format() << "\n";
00384     }
00385   }
00386 }
00387 
00388 ////////////////////////////////////////////////////////////////////
00389 //     Function: DXVertexBufferContext9::create_vbuffer
00390 //       Access: Public
00391 //  Description: Creates a new vertex buffer (but does not upload data
00392 //               to it).
00393 ////////////////////////////////////////////////////////////////////
00394 void DXVertexBufferContext9::
00395 create_vbuffer(DXScreenData &scrn,
00396                const GeomVertexArrayDataHandle *reader,
00397                string name) {
00398   nassertv(reader->get_object() == get_data());
00399   Thread *current_thread = reader->get_current_thread();
00400 
00401   free_vbuffer ( );
00402 
00403   PStatTimer timer(GraphicsStateGuardian::_create_vertex_buffer_pcollector,
00404                    current_thread);
00405 
00406   int data_size;
00407 
00408   data_size = reader->get_data_size_bytes();
00409 
00410   this -> allocate_vbuffer(scrn, reader);
00411 }
00412 
00413 ////////////////////////////////////////////////////////////////////
00414 //     Function: DXVertexBufferContext9::upload_data
00415 //       Access: Public
00416 //  Description: Copies the latest data from the client store to
00417 //               DirectX.
00418 ////////////////////////////////////////////////////////////////////
00419 bool DXVertexBufferContext9::
00420 upload_data(const GeomVertexArrayDataHandle *reader, bool force) {
00421   nassertr(reader->get_object() == get_data(), false);
00422   nassertr(_vbuffer != NULL, false);
00423   Thread *current_thread = reader->get_current_thread();
00424 
00425   const unsigned char *data_pointer = reader->get_read_pointer(force);
00426   if (data_pointer == NULL) {
00427     return false;
00428   }
00429   int data_size = reader->get_data_size_bytes();
00430 
00431   if (dxgsg9_cat.is_spam()) {
00432     dxgsg9_cat.spam()
00433       << "copying " << data_size
00434       << " bytes into vertex buffer " << _vbuffer << "\n";
00435   }
00436   PStatTimer timer(GraphicsStateGuardian::_load_vertex_buffer_pcollector,
00437                    current_thread);
00438 
00439   HRESULT hr;
00440   BYTE *local_pointer;
00441 
00442   if (_managed) {
00443     hr = _vbuffer->Lock(0, data_size, (void **) &local_pointer, 0);
00444   }
00445   else {
00446     hr = _vbuffer->Lock(0, data_size, (void **) &local_pointer, D3DLOCK_DISCARD);
00447   }
00448   if (FAILED(hr)) {
00449     dxgsg9_cat.error()
00450       << "VertexBuffer::Lock failed" << D3DERRORSTRING(hr);
00451     return false;
00452   }
00453 
00454   GraphicsStateGuardian::_data_transferred_pcollector.add_level(data_size);
00455   memcpy(local_pointer, data_pointer, data_size);
00456 
00457   _vbuffer->Unlock();
00458   return true;
00459 }
 All Classes Functions Variables Enumerations