Panda3D
Loading...
Searching...
No Matches
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"
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
31TypeHandle 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 */
101void DXShaderContext9::
102release_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 */
121bool DXShaderContext9::
122bind(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 */
159void DXShaderContext9::
160unbind(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
185PN_stdfloat *global_data = 0;
186ShaderContext::ShaderMatSpec *global_shader_mat_spec = 0;
187InternalName *global_internal_name_0 = 0;
188InternalName *global_internal_name_1 = 0;
189#endif
190
192issue_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 LMatrix3f temp_matrix3;
249
250 hr = D3D_OK;
251
252 const float *data;
253 data = temp_matrix.get_data();
254
255#if DEBUG_SHADER
256 // DEBUG
257 global_data = (PN_stdfloat *)data;
258 global_shader_mat_spec = &spec;
259 global_internal_name_0 = global_shader_mat_spec->_arg[0];
260 global_internal_name_1 = global_shader_mat_spec->_arg[1];
261#endif
262
263 switch (spec._piece) {
264 case Shader::SMP_whole:
265 // TRANSPOSE REQUIRED
266 temp_matrix.transpose_in_place();
267 data = temp_matrix.get_data();
268
269 hr = cgD3D9SetUniform(p, data);
270 break;
271
272 case Shader::SMP_transpose:
273 // NO TRANSPOSE REQUIRED
274 hr = cgD3D9SetUniform(p, data);
275 break;
276
277 case Shader::SMP_row0:
278 hr = cgD3D9SetUniform(p, data + 0);
279 break;
280 case Shader::SMP_row1:
281 hr = cgD3D9SetUniform(p, data + 4);
282 break;
283 case Shader::SMP_row2:
284 hr = cgD3D9SetUniform(p, data + 8);
285 break;
286 case Shader::SMP_row3x1:
287 case Shader::SMP_row3x2:
288 case Shader::SMP_row3x3:
289 case Shader::SMP_row3:
290 hr = cgD3D9SetUniform(p, data + 12);
291 break;
292
293 case Shader::SMP_col0:
294 v[0] = data[0]; v[1] = data[4]; v[2] = data[8]; v[3] = data[12];
295 hr = cgD3D9SetUniform(p, v);
296 break;
297 case Shader::SMP_col1:
298 v[0] = data[1]; v[1] = data[5]; v[2] = data[9]; v[3] = data[13];
299 hr = cgD3D9SetUniform(p, v);
300 break;
301 case Shader::SMP_col2:
302 v[0] = data[2]; v[1] = data[6]; v[2] = data[10]; v[3] = data[14];
303 hr = cgD3D9SetUniform(p, v);
304 break;
305 case Shader::SMP_col3:
306 v[0] = data[3]; v[1] = data[7]; v[2] = data[11]; v[3] = data[15];
307 hr = cgD3D9SetUniform(p, v);
308 break;
309
310 case Shader::SMP_upper3x3:
311 // TRANSPOSE REQUIRED
312 temp_matrix3 = temp_matrix.get_upper_3();
313 temp_matrix3.transpose_in_place();
314 data = temp_matrix3.get_data();
315
316 hr = cgD3D9SetUniform(p, data);
317 break;
318
319 case Shader::SMP_transpose3x3:
320 // NO TRANSPOSE REQUIRED
321 temp_matrix3 = temp_matrix.get_upper_3();
322 data = temp_matrix3.get_data();
323
324 hr = cgD3D9SetUniform(p, data);
325 break;
326
327 case Shader::SMP_cell15:
328 hr = cgD3D9SetUniform(p, data + 15);
329 continue;
330 case Shader::SMP_cell14:
331 hr = cgD3D9SetUniform(p, data + 14);
332 continue;
333 case Shader::SMP_cell13:
334 hr = cgD3D9SetUniform(p, data + 13);
335 continue;
336
337 default:
338 dxgsg9_cat.error()
339 << "issue_parameters () SMP parameter type not implemented " << spec._piece << "\n";
340 break;
341 }
342
343 if (FAILED(hr)) {
344 std::string name = "unnamed";
345
346 if (spec._arg[0]) {
347 name = spec._arg[0]->get_basename();
348 }
349
350 dxgsg9_cat.error()
351 << "NAME " << name << "\n" << "MAT TYPE " << spec._piece
352 << " cgD3D9SetUniform failed " << D3DERRORSTRING(hr);
353
354 CGerror error = cgGetError();
355 if (error != CG_NO_ERROR) {
356 dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n";
357 }
358 }
359 }
360 }
361 }
362 }
363#endif
364}
365
366/**
367 * Disable all the vertex arrays used by this shader.
368 */
369void DXShaderContext9::
370disable_shader_vertex_arrays(GSG *gsg) {
371 LPDIRECT3DDEVICE9 device = gsg->_screen->_d3d_device;
372
373 for (int array_index = 0; array_index < _num_bound_streams; ++array_index) {
374 device->SetStreamSource(array_index, nullptr, 0, 0);
375 }
376 _num_bound_streams = 0;
377}
378
379/**
380 * Disables all vertex arrays used by the previous shader, then enables all
381 * the vertex arrays needed by this shader. Extracts the relevant vertex
382 * array data from the gsg. The current implementation is inefficient,
383 * because it may unnecessarily disable arrays then immediately reenable them.
384 * We may optimize this someday.
385 */
387update_shader_vertex_arrays(DXShaderContext9 *prev, GSG *gsg, bool force) {
388 if (prev) prev->disable_shader_vertex_arrays(gsg);
389#ifdef HAVE_CG
390 if (!_cg_program) {
391 return true;
392 }
393
394#ifdef SUPPORT_IMMEDIATE_MODE
395/*
396 if (gsg->_use_sender) {
397 dxgsg9_cat.error() << "immediate mode shaders not implemented yet\n";
398 } else
399*/
400#endif // SUPPORT_IMMEDIATE_MODE
401 {
402 int nvarying = _shader->_var_spec.size();
403 LPDIRECT3DDEVICE9 device = gsg->_screen->_d3d_device;
404 HRESULT hr;
405
406 // Discard and recreate the VertexElementArray. This thrashes pretty
407 // bad....
408 if (_vertex_element_array != nullptr) {
409 delete _vertex_element_array;
410 }
411 _vertex_element_array = new VertexElementArray(nvarying + 2);
412 VertexElementArray* vertex_element_array = _vertex_element_array;
413
414 // Experimentally determined that DX doesn't like us crossing the streams!
415 // It seems to be okay with out-of-order offsets in both source and
416 // destination, but it wants all stream X entries grouped together, then
417 // all stream Y entries, etc. To accomplish this out outer loop processes
418 // arrays ("streams"), and we repeatedly iterate the parameters to pull
419 // out only those for a single stream.
420
421 bool apply_white_color = false;
422
423 int number_of_arrays = gsg->_data_reader->get_num_arrays();
424 for (int array_index = 0; array_index < number_of_arrays; ++array_index) {
425 const GeomVertexArrayDataHandle* array_reader =
426 gsg->_data_reader->get_array_reader(array_index);
427 if (array_reader == nullptr) {
428 dxgsg9_cat.error() << "Unable to get reader for array " << array_index << "\n";
429 continue;
430 }
431
432 for (int var_index = 0; var_index < nvarying; ++var_index) {
433 CGparameter p = _cg_parameter_map[_shader->_var_spec[var_index]._id._seqno];
434 if (p == nullptr) {
435 dxgsg9_cat.info() <<
436 "No parameter in map for parameter " << var_index <<
437 " (probably optimized away)\n";
438 continue;
439 }
440
441 InternalName *name = _shader->_var_spec[var_index]._name;
442
443 // This is copied from the GL version of this function, and I've yet
444 // to 100% convince myself that it works properly....
445 int texslot = _shader->_var_spec[var_index]._append_uv;
446 if (texslot >= 0 && texslot < gsg->_state_texture->get_num_on_stages()) {
447 TextureStage *stage = gsg->_state_texture->get_on_stage(texslot);
448 InternalName *texname = stage->get_texcoord_name();
449 if (name == InternalName::get_texcoord()) {
450 name = texname;
451 } else if (texname != InternalName::get_texcoord()) {
452 name = name->append(texname->get_basename());
453 }
454 }
455
456 if (name == InternalName::get_color() && !gsg->_vertex_colors_enabled) {
457 apply_white_color = true;
458 continue;
459 }
460
461 const GeomVertexArrayDataHandle *param_array_reader;
462 Geom::NumericType numeric_type;
463 int num_values, start, stride;
464 if (!gsg->_data_reader->get_array_info(name, param_array_reader,
465 num_values, numeric_type,
466 start, stride)) {
467 // This is apparently not an error (actually I think it is, just not
468 // a fatal one). The GL implementation fails silently in this case,
469 // but the net result is that we end up not supplying input for a
470 // shader parameter, which can cause Bad Things to happen so I'd
471 // like to at least get a hint as to what's gone wrong.
472 dxgsg9_cat.info() << "Geometry contains no data for shader parameter " << *name << "\n";
473 if (name == InternalName::get_color()) {
474 apply_white_color = true;
475 }
476 continue;
477 }
478
479 // If not associated with the array we're working on, move on.
480 if (param_array_reader != array_reader) {
481 continue;
482 }
483
484 const char *semantic = cgGetParameterSemantic(p);
485 if (semantic == nullptr) {
486 dxgsg9_cat.error() << "Unable to retrieve semantic for parameter " << var_index << "\n";
487 continue;
488 }
489
490 if (strncmp(semantic, "POSITION", strlen("POSITION")) == 0) {
491 if (numeric_type == Geom::NT_float32) {
492 switch (num_values) {
493 case 3:
494 vertex_element_array->add_position_xyz_vertex_element(array_index, start);
495 break;
496 case 4:
497 vertex_element_array->add_position_xyzw_vertex_element(array_index, start);
498 break;
499 default:
500 dxgsg9_cat.error() << "VE ERROR: invalid number of vertex coordinate elements " << num_values << "\n";
501 break;
502 }
503 } else {
504 dxgsg9_cat.error() << "VE ERROR: invalid vertex type " << numeric_type << "\n";
505 }
506 } else if (strncmp(semantic, "TEXCOORD", strlen("TEXCOORD")) == 0) {
507 int slot = atoi(semantic + strlen("TEXCOORD"));
508 if (numeric_type == Geom::NT_float32) {
509 switch (num_values) {
510 case 1:
511 vertex_element_array->add_u_vertex_element(array_index, start, slot);
512 break;
513 case 2:
514 vertex_element_array->add_uv_vertex_element(array_index, start, slot);
515 break;
516 case 3:
517 vertex_element_array->add_uvw_vertex_element(array_index, start, slot);
518 break;
519 case 4:
520 vertex_element_array->add_xyzw_vertex_element(array_index, start, slot);
521 break;
522 default:
523 dxgsg9_cat.error() << "VE ERROR: invalid number of vertex texture coordinate elements " << num_values << "\n";
524 break;
525 }
526 } else {
527 dxgsg9_cat.error() << "VE ERROR: invalid texture coordinate type " << numeric_type << "\n";
528 }
529 } else if (strncmp(semantic, "COLOR", strlen("COLOR")) == 0) {
530 if (numeric_type == Geom::NT_packed_dcba ||
531 numeric_type == Geom::NT_packed_dabc ||
532 numeric_type == Geom::NT_uint8) {
533 switch (num_values) {
534 case 4:
535 vertex_element_array->add_diffuse_color_vertex_element(array_index, start);
536 break;
537 default:
538 dxgsg9_cat.error() << "VE ERROR: invalid color coordinates " << num_values << "\n";
539 break;
540 }
541 } else {
542 dxgsg9_cat.error() << "VE ERROR: invalid color type " << numeric_type << "\n";
543 }
544 } else if (strncmp(semantic, "NORMAL", strlen("NORMAL")) == 0) {
545 if (numeric_type == Geom::NT_float32) {
546 switch (num_values) {
547 case 3:
548 vertex_element_array->add_normal_vertex_element(array_index, start);
549 break;
550 default:
551 dxgsg9_cat.error() << "VE ERROR: invalid number of normal coordinate elements " << num_values << "\n";
552 break;
553 }
554 } else {
555 dxgsg9_cat.error() << "VE ERROR: invalid normal type " << numeric_type << "\n";
556 }
557 } else if (strncmp(semantic, "BINORMAL", strlen("BINORMAL")) == 0) {
558 if (numeric_type == Geom::NT_float32) {
559 switch (num_values) {
560 case 3:
561 vertex_element_array->add_binormal_vertex_element(array_index, start);
562 break;
563 default:
564 dxgsg9_cat.error() << "VE ERROR: invalid number of binormal coordinate elements " << num_values << "\n";
565 break;
566 }
567 } else {
568 dxgsg9_cat.error() << "VE ERROR: invalid binormal type " << numeric_type << "\n";
569 }
570 } else if (strncmp(semantic, "TANGENT", strlen("TANGENT")) == 0) {
571 if (numeric_type == Geom::NT_float32) {
572 switch (num_values) {
573 case 3:
574 vertex_element_array->add_tangent_vertex_element(array_index, start);
575 break;
576 default:
577 dxgsg9_cat.error() << "VE ERROR: invalid number of tangent coordinate elements " << num_values << "\n";
578 break;
579 }
580 } else {
581 dxgsg9_cat.error() << "VE ERROR: invalid tangent type " << numeric_type << "\n";
582 }
583 } else {
584 dxgsg9_cat.error() << "Unsupported semantic " << semantic << " for parameter " << var_index << "\n";
585 }
586 }
587
588 // Get the vertex buffer for this array.
590 if (!gsg->setup_array_data(dvbc, array_reader, force)) {
591 dxgsg9_cat.error() << "Unable to setup vertex buffer for array " << array_index << "\n";
592 continue;
593 }
594
595 // Bind this array as the data source for the corresponding stream.
596 const GeomVertexArrayFormat *array_format = array_reader->get_array_format();
597 hr = device->SetStreamSource(array_index, dvbc->_vbuffer, 0, array_format->get_stride());
598 if (FAILED(hr)) {
599 dxgsg9_cat.error() << "SetStreamSource failed" << D3DERRORSTRING(hr);
600 }
601 }
602
603 _num_bound_streams = number_of_arrays;
604
605 if (apply_white_color) {
606 // The shader needs a vertex color, but vertex colors are disabled.
607 // Bind a vertex buffer containing only one white colour.
608 int array_index = number_of_arrays;
609 LPDIRECT3DVERTEXBUFFER9 vbuffer = gsg->get_white_vbuffer();
610 hr = device->SetStreamSource(array_index, vbuffer, 0, 0);
611 if (FAILED(hr)) {
612 dxgsg9_cat.error() << "SetStreamSource failed" << D3DERRORSTRING(hr);
613 }
614 vertex_element_array->add_diffuse_color_vertex_element(array_index, 0);
615 ++_num_bound_streams;
616 }
617
618 if (_vertex_element_array != nullptr &&
619 _vertex_element_array->add_end_vertex_element()) {
620 if (dxgsg9_cat.is_debug()) {
621 // Note that the currently generated vertex declaration works but
622 // never validates. My theory is that this is due to the shader
623 // programs always using float4 whereas the vertex declaration
624 // correctly sets the number of inputs (float2, float3, etc.).
625 if (cgD3D9ValidateVertexDeclaration(_cg_program,
626 _vertex_element_array->_vertex_element_array) == CG_TRUE) {
627 dxgsg9_cat.debug() << "cgD3D9ValidateVertexDeclaration succeeded\n";
628 } else {
629 dxgsg9_cat.debug() << "cgD3D9ValidateVertexDeclaration failed\n";
630 }
631 }
632
633 // Discard the old VertexDeclaration. This thrashes pretty bad....
634 if (_vertex_declaration != nullptr) {
635 _vertex_declaration->Release();
636 _vertex_declaration = nullptr;
637 }
638
639 hr = device->CreateVertexDeclaration(_vertex_element_array->_vertex_element_array,
640 &_vertex_declaration);
641 if (FAILED(hr)) {
642 dxgsg9_cat.error() << "CreateVertexDeclaration failed" << D3DERRORSTRING(hr);
643 } else {
644 hr = device->SetVertexDeclaration(_vertex_declaration);
645 if (FAILED(hr)) {
646 dxgsg9_cat.error() << "SetVertexDeclaration failed" << D3DERRORSTRING(hr);
647 }
648 }
649 } else {
650 dxgsg9_cat.error() << "VertexElementArray creation failed\n";
651 }
652 }
653#endif // HAVE_CG
654
655 return true;
656}
657
658/**
659 * Disable all the texture bindings used by this shader.
660 */
661void DXShaderContext9::
662disable_shader_texture_bindings(GSG *gsg) {
663#ifdef HAVE_CG
664 if (_cg_program) {
665 for (size_t i = 0; i < _shader->_tex_spec.size(); ++i) {
666 CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno];
667 if (p == nullptr) {
668 continue;
669 }
670 int texunit = cgGetParameterResourceIndex(p);
671
672 HRESULT hr;
673
674 hr = gsg->_d3d_device->SetTexture(texunit, nullptr);
675 if (FAILED(hr)) {
676 dxgsg9_cat.error()
677 << "SetTexture(" << texunit << ", NULL) failed "
678 << D3DERRORSTRING(hr);
679 }
680 }
681 }
682#endif
683}
684
685/**
686 * Disables all texture bindings used by the previous shader, then enables all
687 * the texture bindings needed by this shader. Extracts the relevant vertex
688 * array data from the gsg. The current implementation is inefficient,
689 * because it may unnecessarily disable textures then immediately reenable
690 * them. We may optimize this someday.
691 */
694 if (prev) {
696 }
697
698#ifdef HAVE_CG
699 if (_cg_program) {
700 for (size_t i = 0; i < _shader->_tex_spec.size(); ++i) {
701 Shader::ShaderTexSpec &spec = _shader->_tex_spec[i];
702 CGparameter p = _cg_parameter_map[spec._id._seqno];
703 if (p == nullptr) {
704 continue;
705 }
706
707 int view = gsg->get_current_tex_view_offset();
708 SamplerState sampler;
709
710 PT(Texture) tex = gsg->fetch_specified_texture(spec, sampler, view);
711 if (tex.is_null()) {
712 continue;
713 }
714
715 if (spec._suffix != 0) {
716 // The suffix feature is inefficient. It is a temporary hack.
717 tex = tex->load_related(spec._suffix);
718 }
719
720 if (tex->get_texture_type() != spec._desired_type) {
721 continue;
722 }
723
724 TextureContext *tc = tex->prepare_now(view, gsg->_prepared_objects, gsg);
725 if (tc == nullptr) {
726 continue;
727 }
728
729 int texunit = cgGetParameterResourceIndex(p);
730 gsg->apply_texture(texunit, tc, sampler);
731 }
732 }
733#endif
734}
735
736// DEBUG CODE TO TEST ASM CODE GENERATED BY Cg
737void assemble_shader_test(char *file_path) {
738 int flags;
739 D3DXMACRO *defines;
740 LPD3DXINCLUDE include;
741 LPD3DXBUFFER shader;
742 LPD3DXBUFFER error_messages;
743
744 flags = 0;
745 defines = 0;
746 include = 0;
747 shader = 0;
748 error_messages = 0;
749
750 D3DXAssembleShaderFromFile(file_path, defines, include, flags, &shader, &error_messages);
751 if (error_messages) {
752 char *error_message;
753
754 error_message = (char *)error_messages->GetBufferPointer();
755 if (error_message) {
756 dxgsg9_cat.error() << error_message;
757 }
758
759 error_messages->Release();
760 }
761}
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,...
void apply_texture(int i, TextureContext *tc, const SamplerState &sampler)
Makes the texture the currently available texture for rendering on the ith stage.
LPDIRECT3DVERTEXBUFFER9 get_white_vbuffer()
Returns a vertex buffer containing only a full-white color.
DXShaderContext9(Shader *s, GSG *gsg)
xyz
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 ...
void disable_shader_vertex_arrays(GSG *gsg)
Disable all the vertex arrays used by this shader.
void disable_shader_texture_bindings(GSG *gsg)
Disable all the texture bindings used by this shader.
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...
void issue_parameters(GSG *gsg, int altered)
This function gets called whenever the RenderState or TransformState has changed, but the Shader itse...
Caches a GeomVertexArrayData in the DirectX device as a vertex buffer.
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
This describes the structure of a single array within a Geom data.
get_stride
Returns the total number of bytes reserved in the array for each vertex.
PT(Texture) fetch_specified_texture(Shader const Shader::ShaderPtrData * fetch_ptr_parameter(const Shader::ShaderPtrSpec &spec)
Return a pointer to struct ShaderPtrData.
const LMatrix4 * fetch_specified_value(Shader::ShaderMatSpec &spec, int altered)
The gsg contains a large number of useful matrices:
Encodes a string name in a hash table, mapping it to a pointer.
get_basename
Return the name represented by just this particular InternalName object, ignoring its parents names.
Represents a set of settings that indicate how a texture is sampled.
The ShaderContext is meant to contain the compiled version of a shader string.
ShaderLanguage get_language() const
Returns the shader language in which this shader was written.
Definition shader.I:132
Filename get_filename(ShaderType type=ST_none) const
Return the Shader's filename for the given shader type.
Definition shader.I:20
This is a special class object that holds all the information returned by a particular GSG to indicat...
Defines the properties of a named stage of the multitexture pipeline.
get_texcoord_name
See set_texcoord_name.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition texture.h:72
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
This class gives the ability for a user-friendly way of creating a vertex declaration for DirectX 9.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.