Panda3D
dxIndexBufferContext9.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file dxIndexBufferContext9.cxx
10  * @author drose
11  * @date 2005-03-18
12  */
13 
14 #include "dxIndexBufferContext9.h"
15 #include "geomPrimitive.h"
16 #include "config_dxgsg9.h"
17 #include "graphicsStateGuardian.h"
18 #include "pStatTimer.h"
19 
20 #define DEBUG_INDEX_BUFFER false
21 
22 TypeHandle DXIndexBufferContext9::_type_handle;
23 
24 /**
25  *
26  */
27 DXIndexBufferContext9::
28 DXIndexBufferContext9(PreparedGraphicsObjects *pgo, GeomPrimitive *data) :
29  IndexBufferContext(pgo, data),
30  _ibuffer(nullptr),
31  _managed(-1) {
32 }
33 
34 /**
35  *
36  */
37 DXIndexBufferContext9::
38 ~DXIndexBufferContext9() {
39  free_ibuffer();
40 }
41 
42 /**
43  * Evicts the page from the LRU. Called internally when the LRU determines
44  * that it is full. May also be called externally when necessary to
45  * explicitly evict the page.
46  *
47  * It is legal for this method to either evict the page as requested, do
48  * nothing (in which case the eviction will be requested again at the next
49  * epoch), or requeue itself on the tail of the queue (in which case the
50  * eviction will be requested again much later).
51  */
53 evict_lru() {
54  dequeue_lru();
55  free_ibuffer();
57  mark_unloaded();
58 }
59 
60 /**
61  * Free index buffer.
62  */
64 free_ibuffer(void) {
65  if (_ibuffer != nullptr) {
66  if (DEBUG_INDEX_BUFFER && dxgsg9_cat.is_debug()) {
67  dxgsg9_cat.debug()
68  << "deleting index buffer " << _ibuffer << "\n";
69  }
70 
71  if (DEBUG_INDEX_BUFFER) {
72  RELEASE(_ibuffer, dxgsg9, "index buffer", RELEASE_ONCE);
73  } else {
74  _ibuffer->Release();
75  }
76 
77  _ibuffer = nullptr;
78  }
79 }
80 
81 /**
82  * Allocates index buffer memory.
83  */
86  const GeomPrimitivePipelineReader *reader) {
87 
88  D3DFORMAT index_type =
89  DXGraphicsStateGuardian9::get_index_type(reader->get_index_type());
90 
91  int data_size;
92  DWORD usage;
93  D3DPOOL pool;
94 
95  data_size = reader->get_data_size_bytes();
96 
97  if (reader->get_index_type() == GeomEnums::NT_uint8) {
98  // We widen 8-bits indices to 16-bits.
99  data_size *= 2;
100  }
101 
102  _managed = scrn._managed_index_buffers;
103  if (_managed)
104  {
105  usage = D3DUSAGE_WRITEONLY;
106  pool = D3DPOOL_MANAGED;
107  }
108  else
109  {
110  usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC;
111  pool = D3DPOOL_DEFAULT;
112  }
113 
114  int attempts;
115  HRESULT hr;
116 
117  attempts = 0;
118  do
119  {
120  hr = scrn._d3d_device->CreateIndexBuffer
121  (data_size, usage, index_type, pool, &_ibuffer, nullptr);
122  attempts++;
123  }
124  while (scrn._dxgsg9 -> check_dx_allocation (hr, data_size, attempts));
125 
126  if (FAILED(hr)) {
127  dxgsg9_cat.warning()
128  << "CreateIndexBuffer failed" << D3DERRORSTRING(hr);
129  _ibuffer = nullptr;
130  } else {
131  if (DEBUG_INDEX_BUFFER && dxgsg9_cat.is_debug()) {
132  dxgsg9_cat.debug()
133  << "creating index buffer " << _ibuffer << ": "
134  << reader->get_num_vertices() << " indices ("
135  << reader->get_index_type() << ")\n";
136  }
137  }
138 }
139 
140 /**
141  * Creates a new index buffer (but does not upload data to it).
142  */
145  const GeomPrimitivePipelineReader *reader) {
146  nassertv(reader->get_object() == get_data());
147  Thread *current_thread = reader->get_current_thread();
148 
149  free_ibuffer();
150 
151  PStatTimer timer(GraphicsStateGuardian::_create_index_buffer_pcollector,
152  current_thread);
153 
154  allocate_ibuffer(scrn, reader);
155 }
156 
157 /**
158  * Copies the latest data from the client store to DirectX.
159  */
161 upload_data(const GeomPrimitivePipelineReader *reader, bool force) {
162  nassertr(reader->get_object() == get_data(), false);
163  Thread *current_thread = reader->get_current_thread();
164 
165  nassertr(_ibuffer != nullptr, false);
166 
167  const unsigned char *data_pointer = reader->get_read_pointer(force);
168  if (data_pointer == nullptr) {
169  return false;
170  }
171  size_t data_size = (size_t)reader->get_data_size_bytes();
172 
173  if (reader->get_index_type() == GeomEnums::NT_uint8) {
174  // We widen 8-bits indices to 16-bits.
175  data_size *= 2;
176  }
177 
178  if (dxgsg9_cat.is_spam()) {
179  dxgsg9_cat.spam()
180  << "copying " << data_size
181  << " bytes into index buffer " << _ibuffer << "\n";
182  }
183  PStatTimer timer(GraphicsStateGuardian::_load_index_buffer_pcollector,
184  current_thread);
185 
186  HRESULT hr;
187  BYTE *local_pointer;
188 
189  if (_managed) {
190  hr = _ibuffer->Lock(0, data_size, (void **) &local_pointer, 0);
191  } else {
192  hr = _ibuffer->Lock(0, data_size, (void **) &local_pointer, D3DLOCK_DISCARD);
193  }
194  if (FAILED(hr)) {
195  dxgsg9_cat.error()
196  << "IndexBuffer::Lock failed" << D3DERRORSTRING(hr);
197  return false;
198  }
199 
200  GraphicsStateGuardian::_data_transferred_pcollector.add_level(data_size);
201 
202  if (reader->get_index_type() == GeomEnums::NT_uint8) {
203  // Widen to 16-bits, as DirectX doesn't support 8-bits indices.
204  uint16_t *ptr = (uint16_t *)local_pointer;
205  for (size_t i = 0; i < data_size; i += 2) {
206  *ptr++ = (uint16_t)*data_pointer++;
207  }
208  } else {
209  memcpy(local_pointer, data_pointer, data_size);
210  }
211 
212  _ibuffer->Unlock();
213  return true;
214 }
void dequeue_lru()
Removes the page from its AdaptiveLru.
Definition: adaptiveLru.I:136
static D3DFORMAT get_index_type(Geom::NumericType numeric_type)
Maps from the Geom's internal numeric type symbols to DirectX's.
bool upload_data(const GeomPrimitivePipelineReader *reader, bool force)
Copies the latest data from the client store to DirectX.
void free_ibuffer()
Free index buffer.
void allocate_ibuffer(DXScreenData &scrn, const GeomPrimitivePipelineReader *reader)
Allocates index buffer memory.
virtual void evict_lru()
Evicts the page from the LRU.
void create_ibuffer(DXScreenData &scrn, const GeomPrimitivePipelineReader *reader)
Creates a new index buffer (but does not upload data to it).
Encapsulates the data from a GeomPrimitive, pre-fetched for one stage of the pipeline.
int get_data_size_bytes() const
Returns the number of bytes stored in the vertices array.
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Definition: geomPrimitive.h:56
This is a special class object that holds all the information returned by a particular GSG to indicat...
void mark_unloaded()
Should be called after the buffer has been forced out of graphics memory.
void update_data_size_bytes(size_t new_data_size_bytes)
Should be called (usually by a derived class) when the on-card size of this object has changed.
GeomPrimitive * get_data() const
Returns the pointer to the client-side array data object.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:30
A table of objects that are saved within the graphics context for reference by handle later.
A thread; that is, a lightweight process.
Definition: thread.h:46
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.