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