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  */
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 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is a special class object that holds all the information returned by a particular GSG to indicat...
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Definition: geomPrimitive.h:56
static D3DFORMAT get_index_type(Geom::NumericType numeric_type)
Maps from the Geom's internal numeric type symbols to DirectX's.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:30
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A table of objects that are saved within the graphics context for reference by handle later.
void dequeue_lru()
Removes the page from its AdaptiveLru.
Definition: adaptiveLru.I:136
void allocate_ibuffer(DXScreenData &scrn, const GeomPrimitivePipelineReader *reader)
Allocates index buffer memory.
void mark_unloaded()
Should be called after the buffer has been forced out of graphics memory.
bool upload_data(const GeomPrimitivePipelineReader *reader, bool force)
Copies the latest data from the client store to DirectX.
A thread; that is, a lightweight process.
Definition: thread.h:46
virtual void evict_lru()
Evicts the page from the LRU.
GeomPrimitive * get_data() const
Returns the pointer to the client-side array data object.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void free_ibuffer()
Free index buffer.
void create_ibuffer(DXScreenData &scrn, const GeomPrimitivePipelineReader *reader)
Creates a new index buffer (but does not upload data to it).
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_data_size_bytes() const
Returns the number of bytes stored in the vertices array.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Encapsulates the data from a GeomPrimitive, pre-fetched for one stage of the pipeline.
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.