Panda3D
dxShaderContext9.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 dxShaderContext9.cxx
10  * @author jyelon
11  * @date 2005-09-01
12  */
13 
15 #include "dxShaderContext9.h"
16 #include "dxVertexBufferContext9.h"
17 
18 #include <io.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <fcntl.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 
25 #ifdef HAVE_CG
26 #include <Cg/cgD3D9.h>
27 #endif
28 
29 #define DEBUG_SHADER 0
30 
31 TypeHandle DXShaderContext9::_type_handle;
32 
33 /**
34  * xyz
35  */
38  _vertex_element_array = nullptr;
39  _vertex_declaration = nullptr;
40 
41  _num_bound_streams = 0;
42 
43  _name = s->get_filename();
44 
45 #ifdef HAVE_CG
46  CGcontext context = DCAST(DXGraphicsStateGuardian9, gsg)->_cg_context;
47 
48  if (s->get_language() == Shader::SL_Cg) {
49  // Ask the shader to compile itself for us and to give us the resulting Cg
50  // program objects.
51  if (!s->cg_compile_for(gsg->_shader_caps, context,
52  _cg_program, _cg_parameter_map)) {
53  return;
54  }
55 
56  // Load the program.
57  DWORD assembly_flags = 0;
58 #if DEBUG_SHADER
59  assembly_flags |= D3DXSHADER_DEBUG;
60 #endif
61 
62  HRESULT hr;
63  bool success = true;
64  hr = cgD3D9LoadProgram(_cg_program, FALSE, assembly_flags);
65  if (FAILED(hr)) {
66  dxgsg9_cat.error()
67  << "cgD3D9LoadProgram failed " << D3DERRORSTRING(hr);
68 
69  CGerror error = cgGetError();
70  if (error != CG_NO_ERROR) {
71  dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n";
72  }
73  release_resources();
74  }
75  }
76 #endif
77 }
78 
79 /**
80  * xyz
81  */
84  release_resources();
85 
86  if (_vertex_declaration != nullptr) {
87  _vertex_declaration->Release();
88  _vertex_declaration = nullptr;
89  }
90 
91  if (_vertex_element_array != nullptr) {
92  delete _vertex_element_array;
93  _vertex_element_array = nullptr;
94  }
95 }
96 
97 /**
98  * Should deallocate all system resources (such as vertex program handles or
99  * Cg contexts).
100  */
101 void DXShaderContext9::
102 release_resources() {
103 #ifdef HAVE_CG
104  if (_cg_program) {
105  cgDestroyProgram(_cg_program);
106  _cg_program = 0;
107  _cg_parameter_map.clear();
108  }
109 #endif
110 
111  // I think we need to call SetStreamSource for _num_bound_streams --
112  // basically the logic from disable_shader_vertex_arrays -- but to do that
113  // we need to introduce logic like the GL code has to manage _last_gsg, so
114  // we can get at the device. Sigh.
115 }
116 
117 /**
118  * This function is to be called to enable a new shader. It also initializes
119  * all of the shader's input parameters.
120  */
121 bool DXShaderContext9::
122 bind(GSG *gsg) {
123  bool bind_state = false;
124 
125 #ifdef HAVE_CG
126  if (_cg_program) {
127  // clear the last cached FVF to make sure the next SetFVF call goes
128  // through
129 
130  gsg->_last_fvf = 0;
131 
132  // Pass in k-parameters and transform-parameters
133  issue_parameters(gsg, Shader::SSD_general);
134 
135  HRESULT hr;
136 
137  // Bind the shaders.
138  bind_state = true;
139  hr = cgD3D9BindProgram(_cg_program);
140  if (FAILED(hr)) {
141  dxgsg9_cat.error() << "cgD3D9BindProgram failed " << D3DERRORSTRING(hr);
142 
143  CGerror error = cgGetError();
144  if (error != CG_NO_ERROR) {
145  dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n";
146  }
147 
148  bind_state = false;
149  }
150  }
151 #endif
152 
153  return bind_state;
154 }
155 
156 /**
157  * This function disables a currently-bound shader.
158  */
159 void DXShaderContext9::
160 unbind(GSG *gsg) {
161 #ifdef HAVE_CG
162  if (_cg_program) {
163  HRESULT hr;
164  hr = cgD3D9UnbindProgram(_cg_program);
165  if (FAILED(hr)) {
166  dxgsg9_cat.error()
167  << "cgD3D9UnbindProgram failed " << D3DERRORSTRING(hr);
168  }
169  }
170 #endif
171 }
172 
173 /**
174  * This function gets called whenever the RenderState or TransformState has
175  * changed, but the Shader itself has not changed. It loads new values into
176  * the shader's parameters.
177  *
178  * If "altered" is false, that means you promise that the parameters for this
179  * shader context have already been issued once, and that since the last time
180  * the parameters were issued, no part of the render state has changed except
181  * the external and internal transforms.
182  */
183 
184 #if DEBUG_SHADER
185 PN_stdfloat *global_data = 0;
186 ShaderContext::ShaderMatSpec *global_shader_mat_spec = 0;
187 InternalName *global_internal_name_0 = 0;
188 InternalName *global_internal_name_1 = 0;
189 #endif
190 
192 issue_parameters(GSG *gsg, int altered) {
193 #ifdef HAVE_CG
194  if (_cg_program) {
195 
196  // Iterate through _ptr parameters
197  for (size_t i = 0; i < _shader->_ptr_spec.size(); ++i) {
198  const Shader::ShaderPtrSpec &spec = _shader->_ptr_spec[i];
199 
200  if (altered & (spec._dep[0] | spec._dep[1])) {
201  const Shader::ShaderPtrData *ptr_data = gsg->fetch_ptr_parameter(spec);
202 
203  if (ptr_data == nullptr) { //the input is not contained in ShaderPtrData
204  release_resources();
205  return;
206  }
207 
208  // Calculate how many elements to transfer; no more than it expects,
209  // but certainly no more than we have.
210  int input_size = std::min(abs(spec._dim[0] * spec._dim[1] * spec._dim[2]), (int)ptr_data->_size);
211 
212  CGparameter p = _cg_parameter_map[spec._id._seqno];
213  switch (ptr_data->_type) {
214  case Shader::SPT_int:
215  cgSetParameterValueic(p, input_size, (int *)ptr_data->_ptr);
216  break;
217 
218  case Shader::SPT_double:
219  cgSetParameterValuedc(p, input_size, (double *)ptr_data->_ptr);
220  break;
221 
222  case Shader::SPT_float:
223  cgSetParameterValuefc(p, input_size, (float *)ptr_data->_ptr);
224  break;
225 
226  default:
227  dxgsg9_cat.error()
228  << spec._id._name << ": unrecognized parameter type\n";
229  release_resources();
230  return;
231  }
232  }
233  }
234 
235  for (size_t i = 0; i < _shader->_mat_spec.size(); ++i) {
236  Shader::ShaderMatSpec &spec = _shader->_mat_spec[i];
237 
238  if (altered & (spec._dep[0] | spec._dep[1])) {
239  CGparameter p = _cg_parameter_map[spec._id._seqno];
240  if (p == nullptr) {
241  continue;
242  }
243  const LMatrix4 *val = gsg->fetch_specified_value(spec, altered);
244  if (val) {
245  HRESULT hr;
246  PN_stdfloat v [4];
247  LMatrix4f temp_matrix = LCAST(float, *val);
248 
249  hr = D3D_OK;
250 
251  const float *data;
252  data = temp_matrix.get_data();
253 
254 #if DEBUG_SHADER
255  // DEBUG
256  global_data = (PN_stdfloat *)data;
257  global_shader_mat_spec = &spec;
258  global_internal_name_0 = global_shader_mat_spec->_arg[0];
259  global_internal_name_1 = global_shader_mat_spec->_arg[1];
260 #endif
261 
262  switch (spec._piece) {
263  case Shader::SMP_whole:
264  // TRANSPOSE REQUIRED
265  temp_matrix.transpose_in_place();
266  data = temp_matrix.get_data();
267 
268  hr = cgD3D9SetUniform(p, data);
269  break;
270 
271  case Shader::SMP_transpose:
272  // NO TRANSPOSE REQUIRED
273  hr = cgD3D9SetUniform(p, data);
274  break;
275 
276  case Shader::SMP_row0:
277  hr = cgD3D9SetUniform(p, data + 0);
278  break;
279  case Shader::SMP_row1:
280  hr = cgD3D9SetUniform(p, data + 4);
281  break;
282  case Shader::SMP_row2:
283  hr = cgD3D9SetUniform(p, data + 8);
284  break;
285  case Shader::SMP_row3x1:
286  case Shader::SMP_row3x2:
287  case Shader::SMP_row3x3:
288  case Shader::SMP_row3:
289  hr = cgD3D9SetUniform(p, data + 12);
290  break;
291 
292  case Shader::SMP_col0:
293  v[0] = data[0]; v[1] = data[4]; v[2] = data[8]; v[3] = data[12];
294  hr = cgD3D9SetUniform(p, v);
295  break;
296  case Shader::SMP_col1:
297  v[0] = data[1]; v[1] = data[5]; v[2] = data[9]; v[3] = data[13];
298  hr = cgD3D9SetUniform(p, v);
299  break;
300  case Shader::SMP_col2:
301  v[0] = data[2]; v[1] = data[6]; v[2] = data[10]; v[3] = data[14];
302  hr = cgD3D9SetUniform(p, v);
303  break;
304  case Shader::SMP_col3:
305  v[0] = data[3]; v[1] = data[7]; v[2] = data[11]; v[3] = data[15];
306  hr = cgD3D9SetUniform(p, v);
307  break;
308 
309  default:
310  dxgsg9_cat.error()
311  << "issue_parameters () SMP parameter type not implemented " << spec._piece << "\n";
312  break;
313  }
314 
315  if (FAILED(hr)) {
316  std::string name = "unnamed";
317 
318  if (spec._arg[0]) {
319  name = spec._arg[0]->get_basename();
320  }
321 
322  dxgsg9_cat.error()
323  << "NAME " << name << "\n" << "MAT TYPE " << spec._piece
324  << " cgD3D9SetUniform failed " << D3DERRORSTRING(hr);
325 
326  CGerror error = cgGetError();
327  if (error != CG_NO_ERROR) {
328  dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n";
329  }
330  }
331  }
332  }
333  }
334  }
335 #endif
336 }
337 
338 /**
339  * Disable all the vertex arrays used by this shader.
340  */
341 void DXShaderContext9::
342 disable_shader_vertex_arrays(GSG *gsg) {
343  LPDIRECT3DDEVICE9 device = gsg->_screen->_d3d_device;
344 
345  for (int array_index = 0; array_index < _num_bound_streams; ++array_index) {
346  device->SetStreamSource(array_index, nullptr, 0, 0);
347  }
348  _num_bound_streams = 0;
349 }
350 
351 /**
352  * Disables all vertex arrays used by the previous shader, then enables all
353  * the vertex arrays needed by this shader. Extracts the relevant vertex
354  * array data from the gsg. The current implementation is inefficient,
355  * because it may unnecessarily disable arrays then immediately reenable them.
356  * We may optimize this someday.
357  */
360  if (prev) prev->disable_shader_vertex_arrays(gsg);
361 #ifdef HAVE_CG
362  if (!_cg_program) {
363  return true;
364  }
365 
366 #ifdef SUPPORT_IMMEDIATE_MODE
367 /*
368  if (gsg->_use_sender) {
369  dxgsg9_cat.error() << "immediate mode shaders not implemented yet\n";
370  } else
371 */
372 #endif // SUPPORT_IMMEDIATE_MODE
373  {
374  int nvarying = _shader->_var_spec.size();
375  LPDIRECT3DDEVICE9 device = gsg->_screen->_d3d_device;
376  HRESULT hr;
377 
378  // Discard and recreate the VertexElementArray. This thrashes pretty
379  // bad....
380  if (_vertex_element_array != nullptr) {
381  delete _vertex_element_array;
382  }
383  _vertex_element_array = new VertexElementArray(nvarying + 2);
384  VertexElementArray* vertex_element_array = _vertex_element_array;
385 
386  // Experimentally determined that DX doesn't like us crossing the streams!
387  // It seems to be okay with out-of-order offsets in both source and
388  // destination, but it wants all stream X entries grouped together, then
389  // all stream Y entries, etc. To accomplish this out outer loop processes
390  // arrays ("streams"), and we repeatedly iterate the parameters to pull
391  // out only those for a single stream.
392 
393  bool apply_white_color = false;
394 
395  int number_of_arrays = gsg->_data_reader->get_num_arrays();
396  for (int array_index = 0; array_index < number_of_arrays; ++array_index) {
397  const GeomVertexArrayDataHandle* array_reader =
398  gsg->_data_reader->get_array_reader(array_index);
399  if (array_reader == nullptr) {
400  dxgsg9_cat.error() << "Unable to get reader for array " << array_index << "\n";
401  continue;
402  }
403 
404  for (int var_index = 0; var_index < nvarying; ++var_index) {
405  CGparameter p = _cg_parameter_map[_shader->_var_spec[var_index]._id._seqno];
406  if (p == nullptr) {
407  dxgsg9_cat.info() <<
408  "No parameter in map for parameter " << var_index <<
409  " (probably optimized away)\n";
410  continue;
411  }
412 
413  InternalName *name = _shader->_var_spec[var_index]._name;
414 
415  // This is copied from the GL version of this function, and I've yet
416  // to 100% convince myself that it works properly....
417  int texslot = _shader->_var_spec[var_index]._append_uv;
418  if (texslot >= 0 && texslot < gsg->_state_texture->get_num_on_stages()) {
419  TextureStage *stage = gsg->_state_texture->get_on_stage(texslot);
420  InternalName *texname = stage->get_texcoord_name();
421  if (name == InternalName::get_texcoord()) {
422  name = texname;
423  } else if (texname != InternalName::get_texcoord()) {
424  name = name->append(texname->get_basename());
425  }
426  }
427 
428  if (name == InternalName::get_color() && !gsg->_vertex_colors_enabled) {
429  apply_white_color = true;
430  continue;
431  }
432 
433  const GeomVertexArrayDataHandle *param_array_reader;
434  Geom::NumericType numeric_type;
435  int num_values, start, stride;
436  if (!gsg->_data_reader->get_array_info(name, param_array_reader,
437  num_values, numeric_type,
438  start, stride)) {
439  // This is apparently not an error (actually I think it is, just not
440  // a fatal one). The GL implementation fails silently in this case,
441  // but the net result is that we end up not supplying input for a
442  // shader parameter, which can cause Bad Things to happen so I'd
443  // like to at least get a hint as to what's gone wrong.
444  dxgsg9_cat.info() << "Geometry contains no data for shader parameter " << *name << "\n";
445  if (name == InternalName::get_color()) {
446  apply_white_color = true;
447  }
448  continue;
449  }
450 
451  // If not associated with the array we're working on, move on.
452  if (param_array_reader != array_reader) {
453  continue;
454  }
455 
456  const char *semantic = cgGetParameterSemantic(p);
457  if (semantic == nullptr) {
458  dxgsg9_cat.error() << "Unable to retrieve semantic for parameter " << var_index << "\n";
459  continue;
460  }
461 
462  if (strncmp(semantic, "POSITION", strlen("POSITION")) == 0) {
463  if (numeric_type == Geom::NT_float32) {
464  switch (num_values) {
465  case 3:
466  vertex_element_array->add_position_xyz_vertex_element(array_index, start);
467  break;
468  case 4:
469  vertex_element_array->add_position_xyzw_vertex_element(array_index, start);
470  break;
471  default:
472  dxgsg9_cat.error() << "VE ERROR: invalid number of vertex coordinate elements " << num_values << "\n";
473  break;
474  }
475  } else {
476  dxgsg9_cat.error() << "VE ERROR: invalid vertex type " << numeric_type << "\n";
477  }
478  } else if (strncmp(semantic, "TEXCOORD", strlen("TEXCOORD")) == 0) {
479  int slot = atoi(semantic + strlen("TEXCOORD"));
480  if (numeric_type == Geom::NT_float32) {
481  switch (num_values) {
482  case 1:
483  vertex_element_array->add_u_vertex_element(array_index, start, slot);
484  break;
485  case 2:
486  vertex_element_array->add_uv_vertex_element(array_index, start, slot);
487  break;
488  case 3:
489  vertex_element_array->add_uvw_vertex_element(array_index, start, slot);
490  break;
491  case 4:
492  vertex_element_array->add_xyzw_vertex_element(array_index, start, slot);
493  break;
494  default:
495  dxgsg9_cat.error() << "VE ERROR: invalid number of vertex texture coordinate elements " << num_values << "\n";
496  break;
497  }
498  } else {
499  dxgsg9_cat.error() << "VE ERROR: invalid texture coordinate type " << numeric_type << "\n";
500  }
501  } else if (strncmp(semantic, "COLOR", strlen("COLOR")) == 0) {
502  if (numeric_type == Geom::NT_packed_dcba ||
503  numeric_type == Geom::NT_packed_dabc ||
504  numeric_type == Geom::NT_uint8) {
505  switch (num_values) {
506  case 4:
507  vertex_element_array->add_diffuse_color_vertex_element(array_index, start);
508  break;
509  default:
510  dxgsg9_cat.error() << "VE ERROR: invalid color coordinates " << num_values << "\n";
511  break;
512  }
513  } else {
514  dxgsg9_cat.error() << "VE ERROR: invalid color type " << numeric_type << "\n";
515  }
516  } else if (strncmp(semantic, "NORMAL", strlen("NORMAL")) == 0) {
517  if (numeric_type == Geom::NT_float32) {
518  switch (num_values) {
519  case 3:
520  vertex_element_array->add_normal_vertex_element(array_index, start);
521  break;
522  default:
523  dxgsg9_cat.error() << "VE ERROR: invalid number of normal coordinate elements " << num_values << "\n";
524  break;
525  }
526  } else {
527  dxgsg9_cat.error() << "VE ERROR: invalid normal type " << numeric_type << "\n";
528  }
529  } else if (strncmp(semantic, "BINORMAL", strlen("BINORMAL")) == 0) {
530  if (numeric_type == Geom::NT_float32) {
531  switch (num_values) {
532  case 3:
533  vertex_element_array->add_binormal_vertex_element(array_index, start);
534  break;
535  default:
536  dxgsg9_cat.error() << "VE ERROR: invalid number of binormal coordinate elements " << num_values << "\n";
537  break;
538  }
539  } else {
540  dxgsg9_cat.error() << "VE ERROR: invalid binormal type " << numeric_type << "\n";
541  }
542  } else if (strncmp(semantic, "TANGENT", strlen("TANGENT")) == 0) {
543  if (numeric_type == Geom::NT_float32) {
544  switch (num_values) {
545  case 3:
546  vertex_element_array->add_tangent_vertex_element(array_index, start);
547  break;
548  default:
549  dxgsg9_cat.error() << "VE ERROR: invalid number of tangent coordinate elements " << num_values << "\n";
550  break;
551  }
552  } else {
553  dxgsg9_cat.error() << "VE ERROR: invalid tangent type " << numeric_type << "\n";
554  }
555  } else {
556  dxgsg9_cat.error() << "Unsupported semantic " << semantic << " for parameter " << var_index << "\n";
557  }
558  }
559 
560  // Get the vertex buffer for this array.
562  if (!gsg->setup_array_data(dvbc, array_reader, force)) {
563  dxgsg9_cat.error() << "Unable to setup vertex buffer for array " << array_index << "\n";
564  continue;
565  }
566 
567  // Bind this array as the data source for the corresponding stream.
568  const GeomVertexArrayFormat *array_format = array_reader->get_array_format();
569  hr = device->SetStreamSource(array_index, dvbc->_vbuffer, 0, array_format->get_stride());
570  if (FAILED(hr)) {
571  dxgsg9_cat.error() << "SetStreamSource failed" << D3DERRORSTRING(hr);
572  }
573  }
574 
575  _num_bound_streams = number_of_arrays;
576 
577  if (apply_white_color) {
578  // The shader needs a vertex color, but vertex colors are disabled.
579  // Bind a vertex buffer containing only one white colour.
580  int array_index = number_of_arrays;
581  LPDIRECT3DVERTEXBUFFER9 vbuffer = gsg->get_white_vbuffer();
582  hr = device->SetStreamSource(array_index, vbuffer, 0, 0);
583  if (FAILED(hr)) {
584  dxgsg9_cat.error() << "SetStreamSource failed" << D3DERRORSTRING(hr);
585  }
586  vertex_element_array->add_diffuse_color_vertex_element(array_index, 0);
587  ++_num_bound_streams;
588  }
589 
590  if (_vertex_element_array != nullptr &&
591  _vertex_element_array->add_end_vertex_element()) {
592  if (dxgsg9_cat.is_debug()) {
593  // Note that the currently generated vertex declaration works but
594  // never validates. My theory is that this is due to the shader
595  // programs always using float4 whereas the vertex declaration
596  // correctly sets the number of inputs (float2, float3, etc.).
597  if (cgD3D9ValidateVertexDeclaration(_cg_program,
598  _vertex_element_array->_vertex_element_array) == CG_TRUE) {
599  dxgsg9_cat.debug() << "cgD3D9ValidateVertexDeclaration succeeded\n";
600  } else {
601  dxgsg9_cat.debug() << "cgD3D9ValidateVertexDeclaration failed\n";
602  }
603  }
604 
605  // Discard the old VertexDeclaration. This thrashes pretty bad....
606  if (_vertex_declaration != nullptr) {
607  _vertex_declaration->Release();
608  _vertex_declaration = nullptr;
609  }
610 
611  hr = device->CreateVertexDeclaration(_vertex_element_array->_vertex_element_array,
612  &_vertex_declaration);
613  if (FAILED(hr)) {
614  dxgsg9_cat.error() << "CreateVertexDeclaration failed" << D3DERRORSTRING(hr);
615  } else {
616  hr = device->SetVertexDeclaration(_vertex_declaration);
617  if (FAILED(hr)) {
618  dxgsg9_cat.error() << "SetVertexDeclaration failed" << D3DERRORSTRING(hr);
619  }
620  }
621  } else {
622  dxgsg9_cat.error() << "VertexElementArray creation failed\n";
623  }
624  }
625 #endif // HAVE_CG
626 
627  return true;
628 }
629 
630 /**
631  * Disable all the texture bindings used by this shader.
632  */
633 void DXShaderContext9::
634 disable_shader_texture_bindings(GSG *gsg) {
635 #ifdef HAVE_CG
636  if (_cg_program) {
637  for (size_t i = 0; i < _shader->_tex_spec.size(); ++i) {
638  CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno];
639  if (p == nullptr) {
640  continue;
641  }
642  int texunit = cgGetParameterResourceIndex(p);
643 
644  HRESULT hr;
645 
646  hr = gsg->_d3d_device->SetTexture(texunit, nullptr);
647  if (FAILED(hr)) {
648  dxgsg9_cat.error()
649  << "SetTexture(" << texunit << ", NULL) failed "
650  << D3DERRORSTRING(hr);
651  }
652  }
653  }
654 #endif
655 }
656 
657 /**
658  * Disables all texture bindings used by the previous shader, then enables all
659  * the texture bindings needed by this shader. Extracts the relevant vertex
660  * array data from the gsg. The current implementation is inefficient,
661  * because it may unnecessarily disable textures then immediately reenable
662  * them. We may optimize this someday.
663  */
666  if (prev) {
668  }
669 
670 #ifdef HAVE_CG
671  if (_cg_program) {
672  for (size_t i = 0; i < _shader->_tex_spec.size(); ++i) {
673  Shader::ShaderTexSpec &spec = _shader->_tex_spec[i];
674  CGparameter p = _cg_parameter_map[spec._id._seqno];
675  if (p == nullptr) {
676  continue;
677  }
678 
679  int view = gsg->get_current_tex_view_offset();
680  SamplerState sampler;
681 
682  PT(Texture) tex = gsg->fetch_specified_texture(spec, sampler, view);
683  if (tex.is_null()) {
684  continue;
685  }
686 
687  if (spec._suffix != 0) {
688  // The suffix feature is inefficient. It is a temporary hack.
689  tex = tex->load_related(spec._suffix);
690  }
691 
692  if (tex->get_texture_type() != spec._desired_type) {
693  continue;
694  }
695 
696  TextureContext *tc = tex->prepare_now(view, gsg->_prepared_objects, gsg);
697  if (tc == nullptr) {
698  continue;
699  }
700 
701  int texunit = cgGetParameterResourceIndex(p);
702  gsg->apply_texture(texunit, tc, sampler);
703  }
704  }
705 #endif
706 }
707 
708 // DEBUG CODE TO TEST ASM CODE GENERATED BY Cg
709 void assemble_shader_test(char *file_path) {
710  int flags;
711  D3DXMACRO *defines;
712  LPD3DXINCLUDE include;
713  LPD3DXBUFFER shader;
714  LPD3DXBUFFER error_messages;
715 
716  flags = 0;
717  defines = 0;
718  include = 0;
719  shader = 0;
720  error_messages = 0;
721 
722  D3DXAssembleShaderFromFile(file_path, defines, include, flags, &shader, &error_messages);
723  if (error_messages) {
724  char *error_message;
725 
726  error_message = (char *)error_messages->GetBufferPointer();
727  if (error_message) {
728  dxgsg9_cat.error() << error_message;
729  }
730 
731  error_messages->Release();
732  }
733 }
A GraphicsStateGuardian for rendering into DirectX9 contexts.
bool setup_array_data(DXVertexBufferContext9 *&vbc, const GeomVertexArrayDataHandle *data, bool force)
Internal function to bind a buffer object for the indicated data array, if appropriate,...
LPDIRECT3DVERTEXBUFFER9 get_white_vbuffer()
Returns a vertex buffer containing only a full-white color.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition: texture.h:71
Caches a GeomVertexArrayData in the DirectX device as a vertex buffer.
Definition: shader.h:49
DXShaderContext9(Shader *s, GSG *gsg)
xyz
void apply_texture(int i, TextureContext *tc, const SamplerState &sampler)
Makes the texture the currently available texture for rendering on the ith stage.
This is a special class object that holds all the information returned by a particular GSG to indicat...
Filename get_filename(ShaderType type=ST_none) const
Return the Shader's filename for the given shader type.
Definition: shader.I:20
void issue_parameters(GSG *gsg, int altered)
This function gets called whenever the RenderState or TransformState has changed, but the Shader itse...
void disable_shader_texture_bindings(GSG *gsg)
Disable all the texture bindings used by this shader.
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
ShaderLanguage get_language() const
Returns the shader language in which this shader was written.
Definition: shader.I:132
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The ShaderContext is meant to contain the compiled version of a shader string.
Definition: shaderContext.h:31
void disable_shader_vertex_arrays(GSG *gsg)
Disable all the vertex arrays used by this shader.
This class gives the ability for a user-friendly way of creating a vertex declaration for DirectX 9.
Encodes a string name in a hash table, mapping it to a pointer.
Definition: internalName.h:38
Represents a set of settings that indicate how a texture is sampled.
Definition: samplerState.h:36
get_stride
Returns the total number of bytes reserved in the array for each vertex.
bool update_shader_vertex_arrays(DXShaderContext9 *prev, GSG *gsg, bool force)
Disables all vertex arrays used by the previous shader, then enables all the vertex arrays needed by ...
This describes the structure of a single array within a Geom data.
get_basename
Return the name represented by just this particular InternalName object, ignoring its parents names.
Definition: internalName.h:62
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
const LMatrix4 * fetch_specified_value(Shader::ShaderMatSpec &spec, int altered)
The gsg contains a large number of useful matrices:
Defines the properties of a named stage of the multitexture pipeline.
Definition: textureStage.h:35
void update_shader_texture_bindings(DXShaderContext9 *prev, GSG *gsg)
Disables all texture bindings used by the previous shader, then enables all the texture bindings need...
get_texcoord_name
See set_texcoord_name.
Definition: textureStage.h:192
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.