Jelajahi Sumber

Yet another work in progress.

aignacio_sf 20 tahun lalu
induk
melakukan
9deba32241

+ 3 - 3
panda/src/dxgsg9/Sources.pp

@@ -7,7 +7,7 @@
 #define WIN_SYS_LIBS \
    d3d9.lib d3dx9.lib dxerr9.lib
    
-#define USE_PACKAGES dx
+#define USE_PACKAGES dx cg cgdx9
 
 #begin lib_target
   #define TARGET dxgsg9
@@ -30,7 +30,7 @@
     dxTextureContext9.h dxTextureContext9.I \
     dxGeomMunger9.h dxGeomMunger9.I \
     dxGraphicsDevice9.h \
-    ../display/lru.h
+    ../display/lru.h \
     
   #define INCLUDED_SOURCES \
     config_dxgsg9.cxx \
@@ -42,6 +42,6 @@
     wdxGraphicsPipe9.cxx \
     wdxGraphicsWindow9.cxx \
     wdxGraphicsBuffer9.cxx \
-
+    dxShaderContext9.cxx 
 
 #end lib_target

+ 444 - 57
panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx

@@ -4,7 +4,7 @@
 ////////////////////////////////////////////////////////////////////
 //
 // PANDA 3D SOFTWARE
-// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+// Copyright (c) 2001 - 2006, Disney Enterprises, Inc.  All rights reserved
 //
 // All use of this software is subject to the terms of the Panda 3d
 // Software license.  You should have received a copy of this license
@@ -68,10 +68,6 @@
 #define DEBUG_LRU false
 
 
-#define DBG_S if (false) {
-#define DBG_E }
-
-
 TypeHandle DXGraphicsStateGuardian9::_type_handle;
 
 D3DMATRIX DXGraphicsStateGuardian9::_d3d_ident_mat;
@@ -134,6 +130,19 @@ DXGraphicsStateGuardian9(const FrameBufferProperties &properties) :
 
   _lru = 0;
   _last_fvf = 0;
+
+  _vertex_shader_version_major = 0;
+  _vertex_shader_version_minor = 0;
+  _pixel_shader_version_major = 0;
+  _pixel_shader_version_minor = 0;
+
+  _vertex_shader_maximum_constants = 0;
+  _supports_stream_offset = false;
+
+#ifdef HAVE_CGDX9
+  _cg_context = 0;
+#endif
+
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -148,11 +157,19 @@ DXGraphicsStateGuardian9::
   }
   free_nondx_resources();
 
-  if (_lru)
-  {
+  if (_lru) {
     delete _lru;
     _lru = 0;
   }
+
+#ifdef HAVE_CGDX9
+  if (_cg_context) {
+    cgD3D9SetDevice (NULL);
+    cgDestroyContext (_cg_context);
+    _cg_context = 0;
+  }
+#endif
+
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -217,13 +234,13 @@ apply_texture(int i, TextureContext *tc) {
     // error or oversight.
     if ((dirty & Texture::DF_image) == 0) {
       dxgsg9_cat.warning()
-  << "Texture " << *dtc->_texture << " has changed mipmap state.\n";
+        << "Texture " << *dtc->_texture << " has changed mipmap state.\n";
     }
 
     if (!dtc->create_texture(*_screen)) {
       // Oops, we can't re-create the texture for some reason.
       dxgsg9_cat.error()
-  << "Unable to re-create texture " << *dtc->_texture << endl;
+        << "Unable to re-create texture " << *dtc->_texture << endl;
       set_texture_stage_state(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
       return;
     }
@@ -313,6 +330,30 @@ release_texture(TextureContext *tc) {
   delete dtc;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DXGraphicsStateGuardian9::prepare_shader
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+ShaderContext *CLP(GraphicsStateGuardian)::
+prepare_shader(ShaderExpansion *se) {
+  CLP(ShaderContext) *result = new CLP(ShaderContext)(se, this);
+  if (this -> _cg_context) return result;
+  delete result;
+  return NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DXGraphicsStateGuardian9::release_shader
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+void CLP(GraphicsStateGuardian)::
+release_shader(ShaderContext *sc) {
+  CLP(ShaderContext) *gsc = DCAST(CLP(ShaderContext), sc);
+  delete gsc;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DXGraphicsStateGuardian9::prepare_vertex_buffer
 //       Access: Public, Virtual
@@ -328,7 +369,7 @@ release_texture(TextureContext *tc) {
 ////////////////////////////////////////////////////////////////////
 VertexBufferContext *DXGraphicsStateGuardian9::
 prepare_vertex_buffer(GeomVertexArrayData *data) {
-  DXVertexBufferContext9 *dvbc = new DXVertexBufferContext9(data);
+  DXVertexBufferContext9 *dvbc = new DXVertexBufferContext9(data, *(this -> _screen));
   return dvbc;
 }
 
@@ -339,9 +380,20 @@ prepare_vertex_buffer(GeomVertexArrayData *data) {
 //               makes it the current vertex buffer for rendering.
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian9::
-apply_vertex_buffer(VertexBufferContext *vbc) {
+apply_vertex_buffer(VertexBufferContext *vbc, CLP(ShaderContext) *shader_context) {
   DXVertexBufferContext9 *dvbc = DCAST(DXVertexBufferContext9, vbc);
 
+  DBG_SH2 dxgsg9_cat.debug ( ) << "apply_vertex_buffer\n"; DBG_E
+
+  bool set_stream_source;
+  HRESULT hr;
+  UINT stream;
+  UINT offset;
+
+  set_stream_source = false;
+  stream = 0;
+  offset = 0;
+
   if (_lru)
   {
     _lru -> access_page (dvbc -> _lru_page);
@@ -360,11 +412,7 @@ apply_vertex_buffer(VertexBufferContext *vbc) {
       add_to_total_buffer_record(dvbc);
       dvbc->mark_loaded();
 
-      _d3d_device->SetStreamSource
-        (0, dvbc->_vbuffer, 0, dvbc->get_data()->get_array_format()->get_stride());
-      _active_vbuffer = dvbc;
-      _active_ibuffer = NULL;
-      add_to_vertex_buffer_record(dvbc);
+      set_stream_source = true;
 
     } else {
       _active_vbuffer = NULL;
@@ -386,24 +434,134 @@ apply_vertex_buffer(VertexBufferContext *vbc) {
     }
 
     if (_active_vbuffer != dvbc) {
-      _d3d_device->SetStreamSource
-        (0, dvbc->_vbuffer, 0, dvbc->get_data()->get_array_format()->get_stride());
+      set_stream_source = true;
+    }
+  }
+
+  if (shader_context == 0)
+  {
+    // FVF MODE
+    if (set_stream_source)
+    {
+      hr = _d3d_device->SetStreamSource
+        (stream, dvbc->_vbuffer, offset, dvbc->get_data()->get_array_format()->get_stride());
+      if (FAILED(hr)) {
+        dxgsg9_cat.error()
+          << "SetStreamSource failed" << D3DERRORSTRING(hr);
+      }
       _active_vbuffer = dvbc;
       _active_ibuffer = NULL;
       add_to_vertex_buffer_record(dvbc);
     }
+
+    if ((dvbc->_fvf != _last_fvf)) {
+      hr = _d3d_device->SetFVF(dvbc->_fvf);
+      if (FAILED(hr)) {
+        dxgsg9_cat.error() << "SetFVF failed" << D3DERRORSTRING(hr);
+      }
+
+      _last_fvf = dvbc->_fvf;
+    }
   }
+  else
+  {
+    // SHADER MODE
+    if (set_stream_source)
+    {
+      if (dvbc -> _direct_3d_vertex_declaration)
+      {
+        if (dvbc -> _shader_context == shader_context)
+        {
+          // same shader as before, no need to remap a new vertex declaration
+        }
+        else
+        {
+          // need to make a new vertex declaration since the new shader may
+          // have a different mapping
+          dvbc -> _direct_3d_vertex_declaration -> Release ( );
+          dvbc -> _direct_3d_vertex_declaration = 0;
+          dvbc -> _shader_context = 0;
+        }
+      }
 
-  if (dvbc->_fvf != _last_fvf) {
-    HRESULT hr = _d3d_device->SetFVF(dvbc->_fvf);
-  #ifndef NDEBUG
-    if (FAILED(hr)) {
-      dxgsg9_cat.error()
-        << "SetVertexShader(0x" << (void*)dvbc->_fvf
-        << ") failed" << D3DERRORSTRING(hr);
+      if (dvbc -> _direct_3d_vertex_declaration == 0 && dvbc -> _vertex_element_type_array)
+      {
+        VertexElementArray *vertex_element_array;
+
+        vertex_element_array = shader_context -> _vertex_element_array;
+        if (vertex_element_array)
+        {
+          int index;
+
+          for (index = 0; index < vertex_element_array -> total_elements; index++)
+          {
+            VERTEX_ELEMENT_TYPE *vertex_element_type;
+            VERTEX_ELEMENT_TYPE *source_vertex_element_type;
+
+            vertex_element_type = &vertex_element_array -> vertex_element_type_array [index];
+
+            // MAP VERTEX ELEMENTS to VERTEX SHADER INPUTS
+            // get offsets from vertex data for certain types of vertex elements
+
+            offset = 0;
+            source_vertex_element_type = dvbc -> _vertex_element_type_array;
+            while (source_vertex_element_type -> id != VS_END)
+            {
+              if (source_vertex_element_type -> id == vertex_element_type -> id)
+              {
+                  offset = source_vertex_element_type -> offset;
+                  break;
+              }
+              source_vertex_element_type++;
+            }
+            if (source_vertex_element_type -> id == VS_END)
+            {
+              dxgsg9_cat.error()
+                << "unable to find a mapping for vertex shader input type="
+                << vertex_element_type -> id
+                << " from vertex elements\n";
+            }
+
+            vertex_element_array -> set_vertex_element_offset (index, offset);
+          }
+
+          hr = _d3d_device -> CreateVertexDeclaration (vertex_element_array -> vertex_element_array, &dvbc -> _direct_3d_vertex_declaration);
+          if (FAILED (hr)) {
+            dxgsg9_cat.error()
+              << "CreateVertexDeclaration failed"
+              << D3DERRORSTRING(hr);
+          }
+
+          dvbc -> _shader_context = shader_context;
+        }
+        else
+        {
+          dxgsg9_cat.error() << "apply_vertex_buffer ( ): shader_context vertex_element_array == 0\n";
+        }
+      }
+
+      offset = 0;
+      hr = _d3d_device->SetStreamSource
+        (stream, dvbc->_vbuffer, offset, dvbc->get_data()->get_array_format()->get_stride());
+      if (FAILED(hr)) {
+        dxgsg9_cat.error()
+          << "SetStreamSource failed" << D3DERRORSTRING(hr);
+      }
+      _active_vbuffer = dvbc;
+      _active_ibuffer = NULL;
+      add_to_vertex_buffer_record(dvbc);
+    }
+
+    if (dvbc -> _direct_3d_vertex_declaration) {
+
+      DBG_SH5  dxgsg9_cat.debug() << "SetVertexDeclaration ( ) \n"; DBG_E
+
+      hr = _d3d_device -> SetVertexDeclaration (dvbc -> _direct_3d_vertex_declaration);
+      if (FAILED(hr)) {
+        dxgsg9_cat.error()
+          << "SetVertexDeclaration failed" << D3DERRORSTRING(hr);
+      }
     }
-  #endif
-    _last_fvf = dvbc->_fvf;
   }
 }
 
@@ -547,7 +705,7 @@ do_clear(const RenderBuffer &buffer) {
   DWORD main_flags = 0;
   DWORD aux_flags = 0;
 
-DBG_S dxgsg9_cat.error ( ) << "DXGraphicsStateGuardian9::do_clear\n"; DBG_E
+  DBG_S dxgsg9_cat.debug ( ) << "DXGraphicsStateGuardian9::do_clear\n"; DBG_E
 
   //set appropriate flags
   if (buffer_type & RenderBuffer::T_back) {
@@ -566,7 +724,7 @@ DBG_S dxgsg9_cat.error ( ) << "DXGraphicsStateGuardian9::do_clear\n"; DBG_E
 
   if ((main_flags | aux_flags) != 0) {
 
-DBG_S dxgsg9_cat.error ( ) << "ccccc DXGraphicsStateGuardian9::really do_clear\n"; DBG_E
+  DBG_S dxgsg9_cat.debug ( ) << "ccccc DXGraphicsStateGuardian9::really do_clear\n"; DBG_E
 
     HRESULT hr = _d3d_device->Clear(0, NULL, main_flags | aux_flags, _d3dcolor_clear_value,
                                     _depth_clear_value, (DWORD)_stencil_clear_value);
@@ -617,7 +775,7 @@ DBG_S dxgsg9_cat.error ( ) << "ccccc DXGraphicsStateGuardian9::really do_clear\n
 void DXGraphicsStateGuardian9::
 prepare_display_region() {
 
-// DBG_S dxgsg9_cat.error ( ) << "DXGraphicsStateGuardian9::PRE prepare_display_region\n"; DBG_E
+// DBG_S dxgsg9_cat.debug ( ) << "DXGraphicsStateGuardian9::PRE prepare_display_region\n"; DBG_E
 
   if (_current_display_region == (DisplayRegion*)0L) {
     dxgsg9_cat.error()
@@ -626,12 +784,12 @@ prepare_display_region() {
   } else if (_current_display_region != _actual_display_region) {
     _actual_display_region = _current_display_region;
 
-// DBG_S dxgsg9_cat.error ( ) << "DXGraphicsStateGuardian9::prepare_display_region\n"; DBG_E
+// DBG_S dxgsg9_cat.debug ( ) << "DXGraphicsStateGuardian9::prepare_display_region\n"; DBG_E
 
     int l, u, w, h;
     _actual_display_region->get_region_pixels_i(l, u, w, h);
 
-DBG_S dxgsg9_cat.error ( ) << "display_region " << l << " " << u << " "  << w << " "  << h << "\n"; DBG_E
+DBG_S dxgsg9_cat.debug ( ) << "display_region " << l << " " << u << " "  << w << " "  << h << "\n"; DBG_E
 
     // Create the viewport
     D3DVIEWPORT9 vp = { l, u, w, h, 0.0f, 1.0f };
@@ -731,7 +889,7 @@ prepare_lens() {
 bool DXGraphicsStateGuardian9::
 begin_frame() {
 
-DBG_S dxgsg9_cat.error ( ) << "^^^^^^^^^^^ begin_frame \n"; DBG_E
+DBG_S dxgsg9_cat.debug ( ) << "^^^^^^^^^^^ begin_frame \n"; DBG_E
 
   GraphicsStateGuardian::begin_frame();
 
@@ -784,7 +942,7 @@ begin_scene() {
     return false;
   }
 
-DBG_S dxgsg9_cat.error ( ) << "DXGraphicsStateGuardian9::begin_scene\n"; DBG_E
+DBG_S dxgsg9_cat.debug ( ) << "DXGraphicsStateGuardian9::begin_scene\n"; DBG_E
 
 /*
   HRESULT hr = _d3d_device->BeginScene();
@@ -823,7 +981,7 @@ DBG_S dxgsg9_cat.error ( ) << "DXGraphicsStateGuardian9::begin_scene\n"; DBG_E
 void DXGraphicsStateGuardian9::
 end_scene() {
 
-DBG_S dxgsg9_cat.error ( ) << "DXGraphicsStateGuardian9::end_scene\n"; DBG_E
+DBG_S dxgsg9_cat.debug ( ) << "DXGraphicsStateGuardian9::end_scene\n"; DBG_E
 
 /*
   HRESULT hr = _d3d_device->EndScene();
@@ -857,7 +1015,7 @@ DBG_S dxgsg9_cat.error ( ) << "DXGraphicsStateGuardian9::end_scene\n"; DBG_E
 void DXGraphicsStateGuardian9::
 end_frame() {
 
-DBG_S dxgsg9_cat.error ( ) << "@@@@@@@@@@ end_frame \n"; DBG_E
+DBG_S dxgsg9_cat.debug ( ) << "@@@@@@@@@@ end_frame \n"; DBG_E
 
   HRESULT hr = _d3d_device->EndScene();
 
@@ -987,14 +1145,48 @@ begin_draw_primitives(const Geom *geom, const GeomMunger *munger,
   }
   nassertr(_vertex_data != (GeomVertexData *)NULL, false);
 
-  const GeomVertexFormat *format = _vertex_data->get_format();
+  DBG_SH5 dxgsg9_cat.debug ( ) << "begin_draw_primitives\n"; DBG_E
 
-  // The munger should have put the FVF data in the first array.
-  const GeomVertexArrayData *data = _vertex_data->get_array(0);
+
+
+// SHADER
+  if (_vertex_array_shader_context==0) {
+    if (_current_shader_context==0) {
+//      ?????       update_standard_vertex_arrays();
+    } else {
+//      ?????       disable_standard_vertex_arrays();
+      _current_shader_context->update_shader_vertex_arrays(NULL,this);
+    }
+  } else {
+    if (_current_shader_context==0) {
+      _vertex_array_shader_context->disable_shader_vertex_arrays(this);
+//      ?????       update_standard_vertex_arrays();
+    } else {
+      _current_shader_context->
+        update_shader_vertex_arrays(_vertex_array_shader_context,this);
+    }
+  }
+  _vertex_array_shader_expansion = _current_shader_expansion;
+  _vertex_array_shader_context = _current_shader_context;
+
+
+// const GeomVertexFormat *format = _vertex_data->get_format();
+
+  const GeomVertexArrayData *data;
+
+  if (_current_shader_context && _vertex_data->get_num_arrays ( ) > 1)
+  {
+    data = _vertex_data->get_array(1);
+  }
+  else
+  {
+    // The munger should have put the FVF data in the first array.
+    data = _vertex_data->get_array(0);
+  }
 
   VertexBufferContext *vbc = ((GeomVertexArrayData *)data)->prepare_now(get_prepared_objects(), this);
   nassertr(vbc != (VertexBufferContext *)NULL, false);
-  apply_vertex_buffer(vbc);
+  apply_vertex_buffer(vbc, _current_shader_context);
 
   const GeomVertexAnimationSpec &animation =
     vertex_data->get_format()->get_animation();
@@ -1088,6 +1280,9 @@ begin_draw_primitives(const Geom *geom, const GeomMunger *munger,
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian9::
 draw_triangles(const GeomTriangles *primitive) {
+
+//  DBG_SH5 dxgsg9_cat.debug ( ) << "draw_triangles 1\n"; DBG_E
+
   _vertices_tri_pcollector.add_level(primitive->get_num_vertices());
   _primitive_batches_tri_pcollector.add_level(1);
   if (primitive->is_indexed()) {
@@ -1100,14 +1295,18 @@ draw_triangles(const GeomTriangles *primitive) {
       nassertv(ibc != (IndexBufferContext *)NULL);
       apply_index_buffer(ibc);
 
+//DBG_SH2 dxgsg9_cat.debug ( ) << "DrawIndexedPrimitive \n"; DBG_E
+
       _d3d_device->DrawIndexedPrimitive
-        (D3DPT_TRIANGLELIST,
-     0,
+        (D3DPT_TRIANGLELIST, 0,
          min_vertex, max_vertex - min_vertex + 1,
          0, primitive->get_num_primitives());
 
     } else {
       // Indexed, client arrays.
+
+//DBG_SH2 dxgsg9_cat.debug ( ) << "draw_indexed_primitive_up \n"; DBG_E
+
       D3DFORMAT index_type = get_index_type(primitive->get_index_type());
       draw_indexed_primitive_up
         (D3DPT_TRIANGLELIST,
@@ -1121,6 +1320,9 @@ draw_triangles(const GeomTriangles *primitive) {
   } else {
     if (_active_vbuffer != NULL) {
       // Nonindexed, vbuffers.
+
+//DBG_SH2 dxgsg9_cat.debug ( ) << "DrawPrimitive D3DPT_TRIANGLELIST \n"; DBG_E
+
       _d3d_device->DrawPrimitive
         (D3DPT_TRIANGLELIST,
          primitive->get_first_vertex(),
@@ -1129,6 +1331,8 @@ draw_triangles(const GeomTriangles *primitive) {
     } else {
       // Nonindexed, client arrays.
 
+//DBG_SH2 dxgsg9_cat.debug ( ) << "draw_primitive_up \n"; DBG_E
+
       draw_primitive_up(D3DPT_TRIANGLELIST, primitive->get_num_primitives(),
       primitive->get_first_vertex(),
       primitive->get_num_vertices(),
@@ -1136,6 +1340,8 @@ draw_triangles(const GeomTriangles *primitive) {
       _vertex_data->get_format()->get_array(0)->get_stride());
     }
   }
+
+//  DBG_SH5 dxgsg9_cat.debug ( ) << "end draw_triangles 1\n"; DBG_E
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1145,6 +1351,9 @@ draw_triangles(const GeomTriangles *primitive) {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian9::
 draw_tristrips(const GeomTristrips *primitive) {
+
+  DBG_SH5 dxgsg9_cat.debug ( ) << "draw_tristrips\n"; DBG_E
+
   if (connect_triangle_strips && _current_fill_mode != RenderModeAttrib::M_wireframe) {
     // One long triangle strip, connected by the degenerate vertices
     // that have already been set up within the primitive.
@@ -1160,13 +1369,17 @@ draw_tristrips(const GeomTristrips *primitive) {
         nassertv(ibc != (IndexBufferContext *)NULL);
         apply_index_buffer(ibc);
 
+//dxgsg9_cat.error ( ) << "DrawIndexedPrimitive D3DPT_TRIANGLESTRIP VERTICES: " << primitive->get_num_vertices ( ) << "\n";
+
         _d3d_device->DrawIndexedPrimitive
-          (D3DPT_TRIANGLESTRIP,
-       0,
+          (D3DPT_TRIANGLESTRIP, 0,
            min_vertex, max_vertex - min_vertex + 1,
            0, primitive->get_num_vertices() - 2);
 
       } else {
+
+//dxgsg9_cat.error ( ) << "draw_indexed_primitive_up D3DPT_TRIANGLESTRIP VERTICES: " << primitive->get_num_vertices ( ) << "\n";
+
         // Indexed, client arrays, one long triangle strip.
         D3DFORMAT index_type = get_index_type(primitive->get_index_type());
         draw_indexed_primitive_up
@@ -1180,6 +1393,9 @@ draw_tristrips(const GeomTristrips *primitive) {
     } else {
       if (_active_vbuffer != NULL) {
         // Nonindexed, vbuffers, one long triangle strip.
+
+//dxgsg9_cat.error ( ) << "DrawPrimitive D3DPT_TRIANGLESTRIP " << primitive->get_first_vertex ( ) << " VERTICES: " << primitive->get_num_vertices ( ) << "\n";
+
         _d3d_device->DrawPrimitive
           (D3DPT_TRIANGLESTRIP,
            primitive->get_first_vertex(),
@@ -1296,6 +1512,9 @@ draw_tristrips(const GeomTristrips *primitive) {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian9::
 draw_trifans(const GeomTrifans *primitive) {
+
+  DBG_SH5 dxgsg9_cat.debug ( ) << "draw_trifans\n"; DBG_E
+
   CPTA_int ends = primitive->get_ends();
   _primitive_batches_trifan_pcollector.add_level(ends.size());
 
@@ -1324,8 +1543,7 @@ draw_trifans(const GeomTrifans *primitive) {
         unsigned int min = mins.get_data1i();
         unsigned int max = maxs.get_data1i();
         _d3d_device->DrawIndexedPrimitive
-          (D3DPT_TRIANGLEFAN,
-       0,
+          (D3DPT_TRIANGLEFAN, 0,
            min, max - min + 1,
            start, ends[i] - start - 2);
 
@@ -2027,6 +2245,13 @@ reset() {
   D3DCAPS9 d3d_caps;
   _d3d_device->GetDeviceCaps(&d3d_caps);
 
+  _vertex_shader_version_major = D3DSHADER_VERSION_MAJOR (d3d_caps.VertexShaderVersion);
+  _vertex_shader_version_minor = D3DSHADER_VERSION_MINOR (d3d_caps.VertexShaderVersion);
+  _pixel_shader_version_major = D3DSHADER_VERSION_MAJOR (d3d_caps.PixelShaderVersion);
+  _pixel_shader_version_minor = D3DSHADER_VERSION_MINOR (d3d_caps.PixelShaderVersion);
+  _vertex_shader_maximum_constants = d3d_caps.MaxVertexShaderConst;
+  _supports_stream_offset = (d3d_caps.DevCaps2 & D3DDEVCAPS2_STREAMOFFSET) != 0;
+
   if (dxgsg9_cat.is_debug()) {
     dxgsg9_cat.debug()
       << "\nHwTransformAndLight = " << ((d3d_caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0)
@@ -2049,11 +2274,33 @@ reset() {
       << "\nD3DTEXOPCAPS_MULTIPLYADD = " << ((d3d_caps.TextureOpCaps & D3DTEXOPCAPS_MULTIPLYADD) != 0)
       << "\nD3DTEXOPCAPS_LERP = " << ((d3d_caps.TextureOpCaps & D3DTEXOPCAPS_LERP) != 0)
       << "\nD3DPMISCCAPS_TSSARGTEMP = " << ((d3d_caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP) != 0)
+      << "\nVertexShaderVersion = " << _vertex_shader_version_major << "." << _vertex_shader_version_minor
+      << "\nPixelShaderVersion = " << _pixel_shader_version_major << "." << _pixel_shader_version_minor
+      << "\nMaxVertexShaderConst = " << _vertex_shader_maximum_constants
+      << "\nsupport stream offset = " << _supports_stream_offset
       << "\n";
   }
 
   this -> reset_render_states ( );
 
+  // minimum shader requirements
+  if (_vertex_shader_version_major >= 1 &&
+      _pixel_shader_version_major >= 1) {
+    _supports_basic_shaders = true;
+  }
+
+#ifdef HAVE_CGDX9
+  if (_cg_context) {
+    cgD3D9SetDevice (NULL);
+    cgDestroyContext (_cg_context);
+    _cg_context = 0;
+  }
+  if (_cg_context == 0) {
+    _cg_context = cgCreateContext ( );
+    cgD3D9SetDevice (_d3d_device);
+  }
+#endif
+
   _max_vertices_per_array = d3d_caps.MaxVertexIndex;
   _max_vertices_per_primitive = d3d_caps.MaxPrimitiveCount;
 
@@ -2312,6 +2559,13 @@ reset() {
   // must check (_screen->_d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_BLENDOP) (yes on GF2/Radeon8500, no on TNT)
   set_render_state(D3DRS_BLENDOP, D3DBLENDOP_ADD);
 
+  _current_shader_expansion = (ShaderExpansion *)NULL;
+  _current_shader_context = (CLP(ShaderContext) *)NULL;
+  _vertex_array_shader_expansion = (ShaderExpansion *)NULL;
+  _vertex_array_shader_context = (CLP(ShaderContext) *)NULL;
+  _texture_binding_shader_expansion = (ShaderExpansion *)NULL;
+  _texture_binding_shader_context = (CLP(ShaderContext) *)NULL;
+
   PRINT_REFCNT(dxgsg9, _d3d_device);
 }
 
@@ -2375,8 +2629,31 @@ do_issue_transform() {
   const TransformState *transform = _internal_transform;
   DO_PSTATS_STUFF(_transform_state_pcollector.add_level(1));
 
-  const D3DMATRIX *d3d_mat = (const D3DMATRIX *)transform->get_mat().get_data();
-  _d3d_device->SetTransform(D3DTS_WORLD, d3d_mat);
+  if (_current_shader_context) {
+    _current_shader_context->issue_transform(this);
+
+// ??? NO NEED TO SET THE D3D TRANSFORM VIA SetTransform SINCE THE TRANSFORM IS ONLY USED IN THE SHADER
+    const D3DMATRIX *d3d_mat = (const D3DMATRIX *)transform->get_mat().get_data();
+    _d3d_device->SetTransform(D3DTS_WORLD, d3d_mat);
+
+  }
+  else {
+    const D3DMATRIX *d3d_mat = (const D3DMATRIX *)transform->get_mat().get_data();
+    _d3d_device->SetTransform(D3DTS_WORLD, d3d_mat);
+
+// DEBUG PRINT
+/*
+    const float *data;
+    data = &d3d_mat -> _11;
+        dxgsg9_cat.debug ( ) << "do_issue_transform\n" <<
+          data[ 0] << " " << data[ 1] << " " << data[ 2] << " " << data[ 3] << "\n" <<
+          data[ 4] << " " << data[ 5] << " " << data[ 6] << " " << data[ 7] << "\n" <<
+          data[ 8] << " " << data[ 9] << " " << data[10] << " " << data[11] << "\n" <<
+          data[12] << " " << data[13] << " " << data[14] << " " << data[15] << "\n";
+*/
+
+  }
+
   _transform_stale = false;
 
   if (_auto_rescale_normal) {
@@ -2404,6 +2681,60 @@ do_issue_alpha_test() {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DXGraphicsStateGuardian9::do_issue_shader
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+void CLP(GraphicsStateGuardian)::
+do_issue_shader() {
+
+  DBG_SH3  dxgsg9_cat.debug ( ) << "SHADER: do_issue_shader\n"; DBG_E
+
+  CLP(ShaderContext) *context = 0;
+  ShaderExpansion *expansion = _target_rs->get_shader_expansion();
+  if (expansion == 0) {
+    if (_target._shader->get_shader() != 0) {
+      expansion = _target._shader->get_shader()->macroexpand(_target_rs);
+      // I am casting away the const-ness of this pointer, because
+      // the 'shader-expansion' field is just a cache.
+      ((RenderState *)((const RenderState*)_target_rs))->
+        set_shader_expansion(expansion);
+    }
+  }
+
+  if (expansion) {
+    context = (CLP(ShaderContext) *)(expansion->prepare_now(get_prepared_objects(), this));
+  }
+
+  if (context == 0) {
+    if (_current_shader_context != 0) {
+      _current_shader_context->unbind(this);
+      _current_shader_expansion = 0;
+      _current_shader_context = 0;
+    }
+    return;
+  }
+
+  if (context != _current_shader_context) {
+    // Use a completely different shader than before.
+    // Unbind old shader, bind the new one.
+    if (_current_shader_context != 0) {
+      _current_shader_context->unbind(this);
+      _current_shader_context = 0;
+      _current_shader_expansion = 0;
+    }
+    if (context != 0) {
+      context->bind(this);
+      _current_shader_expansion = expansion;
+      _current_shader_context = context;
+    }
+  } else {
+    // Use the same shader as before, but with new input arguments.
+    context->issue_parameters(this);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DXGraphicsStateGuardian9::do_issue_render_mode
 //       Access: Protected
@@ -2711,11 +3042,6 @@ set_state_and_transform(const RenderState *target,
     _state._shade_model = _target._shade_model;
   }
 
-  // Shaders not implemented under DX8
-  if (_target._shader != _state._shader) {
-    _state._shader = _target._shader;
-  }
-
   if (_target._tex_gen != _state._tex_gen) {
     _state._texture = 0;
     _state._tex_gen = _target._tex_gen;
@@ -2734,6 +3060,12 @@ set_state_and_transform(const RenderState *target,
     _state._color_blend = _target._color_blend;
   }
 
+  if (_target._shader != _state._shader) {
+    do_issue_shader();
+    _state._shader = _target._shader;
+    _state._texture = 0;
+  }
+
   if (_target._texture != _state._texture) {
     do_issue_texture();
     _state._texture = _target._texture;
@@ -2985,13 +3317,69 @@ do_issue_material() {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DXGraphicsStateGuardian9::do_issue_texture
-//       Access: Public, Virtual
+//       Access: Protected
 //  Description:
 ////////////////////////////////////////////////////////////////////
-void DXGraphicsStateGuardian9::
+void CLP(GraphicsStateGuardian)::
 do_issue_texture() {
   DO_PSTATS_STUFF(_texture_state_pcollector.add_level(1));
 
+  if (_texture_binding_shader_context==0) {
+    if (_current_shader_context==0) {
+      update_standard_texture_bindings();
+    } else {
+      disable_standard_texture_bindings();
+      _current_shader_context->update_shader_texture_bindings(NULL,this);
+    }
+  } else {
+    if (_current_shader_context==0) {
+      _texture_binding_shader_context->disable_shader_texture_bindings(this);
+      update_standard_texture_bindings();
+    } else {
+      _current_shader_context->
+        update_shader_texture_bindings(_texture_binding_shader_context,this);
+    }
+  }
+  _texture_binding_shader_expansion = _current_shader_expansion;
+  _texture_binding_shader_context = _current_shader_context;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DXGraphicsStateGuardian9::disable_standard_texture_bindings
+//       Access: Private
+//  Description:
+////////////////////////////////////////////////////////////////////
+void CLP(GraphicsStateGuardian)::
+disable_standard_texture_bindings() {
+  int num_old_stages = _max_texture_stages;
+  if (_state._texture != (TextureAttrib *)NULL) {
+    num_old_stages = _state._texture->get_num_on_stages();
+  }
+
+  // Disable the texture stages that are no longer used.
+  for (int i = 0; i < num_old_stages; i++) {
+    HRESULT hr;
+
+    hr = _d3d_device -> SetTexture (i, NULL);
+    if (FAILED (hr)) {
+      dxgsg9_cat.error()
+        << "SetTexture ("
+        << i
+        << ", NULL) failed "
+        << D3DERRORSTRING(hr);
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DXGraphicsStateGuardian9::update_standard_texture_bindings
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+void DXGraphicsStateGuardian9::
+update_standard_texture_bindings() {
+  DO_PSTATS_STUFF(_texture_state_pcollector.add_level(1));
+
   int num_stages = _target._texture->get_num_on_stages();
   int num_old_stages = _max_texture_stages;
   if (_state._texture != (TextureAttrib *)NULL) {
@@ -4042,8 +4430,7 @@ show_frame() {
     return;
   }
 
-DBG_S dxgsg9_cat.error ( ) << "- - - - - DXGraphicsStateGuardian9::show_frame\n"; DBG_E
-
+DBG_S dxgsg9_cat.debug ( ) << "- - - - - DXGraphicsStateGuardian9::show_frame\n"; DBG_E
 
   HRESULT hr;
 

+ 109 - 2
panda/src/dxgsg9/dxGraphicsStateGuardian9.h

@@ -4,7 +4,7 @@
 ////////////////////////////////////////////////////////////////////
 //
 // PANDA 3D SOFTWARE
-// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+// Copyright (c) 2001 - 2006, Disney Enterprises, Inc.  All rights reserved
 //
 // All use of this software is subject to the terms of the Panda 3d
 // Software license.  You should have received a copy of this license
@@ -35,6 +35,24 @@
 
 #include "lru.h"
 
+typedef D3DVERTEXELEMENT9 DIRECT_3D_VERTEX_ELEMENT;
+typedef LPDIRECT3DDEVICE9 DIRECT_3D_DEVICE;
+typedef LPDIRECT3DVERTEXDECLARATION9 DIRECT_3D_VERTEX_DECLARATION;
+
+#include "dxShaderContext9.h"
+
+
+#define DEBUG_ENABLE !false
+#define DBG_SH1 if (false && DEBUG_ENABLE) {
+#define DBG_SH2 if (false && DEBUG_ENABLE) {
+#define DBG_SH3 if (false && DEBUG_ENABLE) {
+#define DBG_SH4 if (false && DEBUG_ENABLE) {
+#define DBG_SH5 if (false && DEBUG_ENABLE) {
+#define DBG_VEA if (false && DEBUG_ENABLE) {
+#define DBG_S if (false && DEBUG_ENABLE) {
+#define DBG_E }
+
+
 enum GsgPageType
 {
   GPT_Texture,
@@ -63,8 +81,11 @@ public:
   void apply_texture(int i, TextureContext *tc);
   virtual void release_texture(TextureContext *tc);
 
+  ShaderContext *prepare_shader(ShaderExpansion *se);
+  void release_shader(ShaderContext *sc);
+
   virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data);
-  void apply_vertex_buffer(VertexBufferContext *vbc);
+  void apply_vertex_buffer(VertexBufferContext *vbc, CLP(ShaderContext) *shader_context);
   virtual void release_vertex_buffer(VertexBufferContext *vbc);
 
   virtual IndexBufferContext *prepare_index_buffer(GeomPrimitive *data);
@@ -128,6 +149,7 @@ public:
 protected:
   void do_issue_transform();
   void do_issue_alpha_test();
+  void do_issue_shader();
   void do_issue_render_mode();
   void do_issue_rescale_normal();
   void do_issue_color_write();
@@ -159,6 +181,11 @@ protected:
 
   void do_auto_rescale_normal();
 
+//  void disable_standard_vertex_arrays();
+//  void update_standard_vertex_arrays();
+  void disable_standard_texture_bindings();
+  void update_standard_texture_bindings();
+
 protected:
   INLINE static D3DTEXTUREADDRESS get_texture_wrap_mode(Texture::WrapMode wm);
   INLINE static D3DFOGMODE get_fog_mode_type(Fog::Mode m);
@@ -208,6 +235,11 @@ protected:
 
 public:
   DXScreenData *_screen;
+
+#ifdef HAVE_CGDX9
+  CGcontext _cg_context;
+#endif
+
 protected:
   LPDIRECT3DDEVICE9 _d3d_device;  // same as _screen->_d3d_device, cached for spd
   IDirect3DSwapChain9 *_swap_chain;
@@ -243,6 +275,13 @@ protected:
 
   LMatrix4f _projection_mat;
 
+  PT(ShaderExpansion)  _current_shader_expansion;
+  CLP(ShaderContext)  *_current_shader_context;
+  PT(ShaderExpansion)  _vertex_array_shader_expansion;
+  CLP(ShaderContext)  *_vertex_array_shader_context;
+  PT(ShaderExpansion)  _texture_binding_shader_expansion;
+  CLP(ShaderContext)  *_texture_binding_shader_context;
+
   CPT(DisplayRegion) _actual_display_region;
   const DXVertexBufferContext9 *_active_vbuffer;
   const DXIndexBufferContext9 *_active_ibuffer;
@@ -292,6 +331,14 @@ protected:
   TextureStageStates _texture_stage_states_array [D3D_MAXTEXTURESTAGES];
   TextureRenderStates _texture_render_states_array [MAXIMUM_TEXTURES];
 
+  int _vertex_shader_version_major;
+  int _vertex_shader_version_minor;
+  int _pixel_shader_version_major;
+  int _pixel_shader_version_minor;
+  int _vertex_shader_maximum_constants;
+
+  bool _supports_stream_offset;
+
 public:
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -319,8 +366,68 @@ private:
   friend class wdxGraphicsBuffer9;
   friend class DXVertexBufferContext9;
   friend class DXIndexBufferContext9;
+  friend class CLP(ShaderContext);
 };
 
 #include "dxGraphicsStateGuardian9.I"
 
+
+enum
+{
+  VS_END = 0,
+
+  VS_POSITION_XYZ,
+  VS_POSITION_XYZW,
+  VS_NORMAL,
+  VS_DIFFUSE,
+  VS_SPECULAR,
+  VS_TEXTURE_U,
+  VS_TEXTURE_UV,
+  VS_TEXTURE_UVW,
+  VS_TANGENT,
+  VS_BINORMAL,
+
+  VS_ERROR,
+
+  VS_TOTAL_TYPES
+};
+
+typedef struct
+{
+  int id; // this is VS_XXXXX
+  int index;
+  int stream;
+  int offset;
+}
+VERTEX_ELEMENT_TYPE;
+
+class VertexElementArray
+{
+public:
+
+  VertexElementArray (int maximum_vertex_elements);
+  ~VertexElementArray ( );
+
+  int set_vertex_element_offset (int vertex_element_index, int offset);
+
+  void add_position_xyz_vertex_element (int stream_index);
+  void add_position_xyzw_vertex_element (int stream_index);
+  void add_normal_vertex_element (int stream_index);
+  void add_binormal_vertex_element (int stream_index);
+  void add_tangent_vertex_element (int stream_index);
+  void add_diffuse_color_vertex_element (int stream_index);
+  void add_specular_color_vertex_element (int stream_index);
+  void add_u_vertex_element (int stream_index);
+  void add_uv_vertex_element (int stream_index);
+  void add_uvw_vertex_element (int stream_index);
+  int add_end_vertex_element (void);
+
+  int offset;
+  int total_elements;
+  int maximum_vertex_elements;
+  int vertex_element_type_counter_array [VS_TOTAL_TYPES];
+  DIRECT_3D_VERTEX_ELEMENT *vertex_element_array;
+  VERTEX_ELEMENT_TYPE *vertex_element_type_array;
+};
+
 #endif

+ 344 - 288
panda/src/dxgsg9/dxShaderContext9.cxx

@@ -20,32 +20,6 @@
 
 TypeHandle CLP(ShaderContext)::_type_handle;
 
-class VertexElementArray
-{
-
-public:
-
-  VertexElementArray (int maximum_vertex_elements);
-  ~VertexElementArray ( );
-
-  void add_position_xyz_vertex_element (int stream_index);
-  void add_position_xyzw_vertex_element (int stream_index);
-  void add_normal_vertex_element (int stream_index);
-  void add_binormal_vertex_element (int stream_index);
-  void add_tangent_vertex_element (int stream_index);
-  void add_diffuse_color_vertex_element (int stream_index);
-  void add_specular_color_vertex_element (int stream_index);
-  void add_u_vertex_element (int stream_index);
-  void add_uv_vertex_element (int stream_index);
-  void add_uvw_vertex_element (int stream_index);
-  int add_end_vertex_element (void);
-
-  int offset;
-  int total_elements;
-  int maximum_vertex_elements;
-  DIRECT_3D_VERTEX_ELEMENT *vertex_element_array;
-};
-
 
 VertexElementArray::VertexElementArray (int maximum_vertex_elements)
 {
@@ -53,22 +27,49 @@ VertexElementArray::VertexElementArray (int maximum_vertex_elements)
   this -> total_elements = 0;
   this -> maximum_vertex_elements = maximum_vertex_elements;
   this -> vertex_element_array = new DIRECT_3D_VERTEX_ELEMENT [maximum_vertex_elements];
+  this -> vertex_element_type_array = new VERTEX_ELEMENT_TYPE [maximum_vertex_elements];
+
+  memset (this -> vertex_element_type_counter_array, 0, VS_TOTAL_TYPES * sizeof (int));
 }
 
 VertexElementArray::~VertexElementArray ( )
 {
   delete this -> vertex_element_array;
+  delete this -> vertex_element_type_array;
+}
+
+int VertexElementArray::set_vertex_element_offset (int vertex_element_index, int offset)
+{
+  int state;
+  DIRECT_3D_VERTEX_ELEMENT *vertex_element;
+
+  if (vertex_element_index >= 0 && vertex_element_index < this -> total_elements)
+  {
+    vertex_element = &this -> vertex_element_array [vertex_element_index];
+    vertex_element -> Offset = offset;
+    state = true;
+  }
+
+  return state;
 }
 
 void VertexElementArray::add_position_xyz_vertex_element (int stream_index)
 {
   DIRECT_3D_VERTEX_ELEMENT *vertex_element;
+  VERTEX_ELEMENT_TYPE *vertex_element_type;
 
   if (this -> total_elements < this -> maximum_vertex_elements)
   {
     vertex_element = &this -> vertex_element_array [this -> total_elements];
     memset (vertex_element, 0, sizeof (DIRECT_3D_VERTEX_ELEMENT));
 
+    vertex_element_type = &this -> vertex_element_type_array [this -> total_elements];
+    memset (vertex_element_type, 0, sizeof (VERTEX_ELEMENT_TYPE));
+
+    vertex_element_type -> id = VS_POSITION_XYZ;
+    vertex_element_type -> index = vertex_element_type_counter_array [vertex_element_type -> id];
+    vertex_element_type_counter_array [vertex_element_type -> id]++;
+
     vertex_element -> Stream = stream_index;
     vertex_element -> Offset = this -> offset;
     vertex_element -> Type = D3DDECLTYPE_FLOAT3;
@@ -85,12 +86,20 @@ void VertexElementArray::add_position_xyz_vertex_element (int stream_index)
 void VertexElementArray::add_position_xyzw_vertex_element (int stream_index)
 {
   DIRECT_3D_VERTEX_ELEMENT *vertex_element;
+  VERTEX_ELEMENT_TYPE *vertex_element_type;
 
   if (this -> total_elements < this -> maximum_vertex_elements)
   {
     vertex_element = &this -> vertex_element_array [this -> total_elements];
     memset (vertex_element, 0, sizeof (DIRECT_3D_VERTEX_ELEMENT));
 
+    vertex_element_type = &this -> vertex_element_type_array [this -> total_elements];
+    memset (vertex_element_type, 0, sizeof (VERTEX_ELEMENT_TYPE));
+
+    vertex_element_type -> id = VS_POSITION_XYZW;
+    vertex_element_type -> index = vertex_element_type_counter_array [vertex_element_type -> id];
+    vertex_element_type_counter_array [vertex_element_type -> id]++;
+
     vertex_element -> Stream = stream_index;
     vertex_element -> Offset = this -> offset;
     vertex_element -> Type = D3DDECLTYPE_FLOAT4;
@@ -107,12 +116,20 @@ void VertexElementArray::add_position_xyzw_vertex_element (int stream_index)
 void VertexElementArray::add_normal_vertex_element (int stream_index)
 {
   DIRECT_3D_VERTEX_ELEMENT *vertex_element;
+  VERTEX_ELEMENT_TYPE *vertex_element_type;
 
   if (this -> total_elements < this -> maximum_vertex_elements)
   {
     vertex_element = &this -> vertex_element_array [this -> total_elements];
     memset (vertex_element, 0, sizeof (DIRECT_3D_VERTEX_ELEMENT));
 
+    vertex_element_type = &this -> vertex_element_type_array [this -> total_elements];
+    memset (vertex_element_type, 0, sizeof (VERTEX_ELEMENT_TYPE));
+
+    vertex_element_type -> id = VS_NORMAL;
+    vertex_element_type -> index = vertex_element_type_counter_array [vertex_element_type -> id];
+    vertex_element_type_counter_array [vertex_element_type -> id]++;
+
     vertex_element -> Stream = stream_index;
     vertex_element -> Offset = this -> offset;
     vertex_element -> Type = D3DDECLTYPE_FLOAT3;
@@ -129,12 +146,20 @@ void VertexElementArray::add_normal_vertex_element (int stream_index)
 void VertexElementArray::add_binormal_vertex_element (int stream_index)
 {
   DIRECT_3D_VERTEX_ELEMENT *vertex_element;
+  VERTEX_ELEMENT_TYPE *vertex_element_type;
 
   if (this -> total_elements < this -> maximum_vertex_elements)
   {
     vertex_element = &this -> vertex_element_array [this -> total_elements];
     memset (vertex_element, 0, sizeof (DIRECT_3D_VERTEX_ELEMENT));
 
+    vertex_element_type = &this -> vertex_element_type_array [this -> total_elements];
+    memset (vertex_element_type, 0, sizeof (VERTEX_ELEMENT_TYPE));
+
+    vertex_element_type -> id = VS_BINORMAL;
+    vertex_element_type -> index = vertex_element_type_counter_array [vertex_element_type -> id];
+    vertex_element_type_counter_array [vertex_element_type -> id]++;
+
     vertex_element -> Stream = stream_index;
     vertex_element -> Offset = this -> offset;
     vertex_element -> Type = D3DDECLTYPE_FLOAT3;
@@ -151,12 +176,20 @@ void VertexElementArray::add_binormal_vertex_element (int stream_index)
 void VertexElementArray::add_tangent_vertex_element (int stream_index)
 {
   DIRECT_3D_VERTEX_ELEMENT *vertex_element;
+  VERTEX_ELEMENT_TYPE *vertex_element_type;
 
   if (this -> total_elements < this -> maximum_vertex_elements)
   {
     vertex_element = &this -> vertex_element_array [this -> total_elements];
     memset (vertex_element, 0, sizeof (DIRECT_3D_VERTEX_ELEMENT));
 
+    vertex_element_type = &this -> vertex_element_type_array [this -> total_elements];
+    memset (vertex_element_type, 0, sizeof (VERTEX_ELEMENT_TYPE));
+
+    vertex_element_type -> id = VS_TANGENT;
+    vertex_element_type -> index = vertex_element_type_counter_array [vertex_element_type -> id];
+    vertex_element_type_counter_array [vertex_element_type -> id]++;
+
     vertex_element -> Stream = stream_index;
     vertex_element -> Offset = this -> offset;
     vertex_element -> Type = D3DDECLTYPE_FLOAT3;
@@ -173,12 +206,20 @@ void VertexElementArray::add_tangent_vertex_element (int stream_index)
 void VertexElementArray::add_diffuse_color_vertex_element (int stream_index)
 {
   DIRECT_3D_VERTEX_ELEMENT *vertex_element;
+  VERTEX_ELEMENT_TYPE *vertex_element_type;
 
   if (this -> total_elements < this -> maximum_vertex_elements)
   {
     vertex_element = &this -> vertex_element_array [this -> total_elements];
     memset (vertex_element, 0, sizeof (DIRECT_3D_VERTEX_ELEMENT));
 
+    vertex_element_type = &this -> vertex_element_type_array [this -> total_elements];
+    memset (vertex_element_type, 0, sizeof (VERTEX_ELEMENT_TYPE));
+
+    vertex_element_type -> id = VS_DIFFUSE;
+    vertex_element_type -> index = vertex_element_type_counter_array [vertex_element_type -> id];
+    vertex_element_type_counter_array [vertex_element_type -> id]++;
+
     vertex_element -> Stream = stream_index;
     vertex_element -> Offset = this -> offset;
     vertex_element -> Type = D3DDECLTYPE_D3DCOLOR;
@@ -195,12 +236,20 @@ void VertexElementArray::add_diffuse_color_vertex_element (int stream_index)
 void VertexElementArray::add_specular_color_vertex_element (int stream_index)
 {
   DIRECT_3D_VERTEX_ELEMENT *vertex_element;
+  VERTEX_ELEMENT_TYPE *vertex_element_type;
 
   if (this -> total_elements < this -> maximum_vertex_elements)
   {
     vertex_element = &this -> vertex_element_array [this -> total_elements];
     memset (vertex_element, 0, sizeof (DIRECT_3D_VERTEX_ELEMENT));
 
+    vertex_element_type = &this -> vertex_element_type_array [this -> total_elements];
+    memset (vertex_element_type, 0, sizeof (VERTEX_ELEMENT_TYPE));
+
+    vertex_element_type -> id = VS_SPECULAR;
+    vertex_element_type -> index = vertex_element_type_counter_array [vertex_element_type -> id];
+    vertex_element_type_counter_array [vertex_element_type -> id]++;
+
     vertex_element -> Stream = stream_index;
     vertex_element -> Offset = this -> offset;
     vertex_element -> Type = D3DDECLTYPE_D3DCOLOR;
@@ -217,12 +266,20 @@ void VertexElementArray::add_specular_color_vertex_element (int stream_index)
 void VertexElementArray::add_u_vertex_element (int stream_index)
 {
   DIRECT_3D_VERTEX_ELEMENT *vertex_element;
+  VERTEX_ELEMENT_TYPE *vertex_element_type;
 
   if (this -> total_elements < this -> maximum_vertex_elements)
   {
     vertex_element = &this -> vertex_element_array [this -> total_elements];
     memset (vertex_element, 0, sizeof (DIRECT_3D_VERTEX_ELEMENT));
 
+    vertex_element_type = &this -> vertex_element_type_array [this -> total_elements];
+    memset (vertex_element_type, 0, sizeof (VERTEX_ELEMENT_TYPE));
+
+    vertex_element_type -> id = VS_TEXTURE_U;
+    vertex_element_type -> index = vertex_element_type_counter_array [vertex_element_type -> id];
+    vertex_element_type_counter_array [vertex_element_type -> id]++;
+
     vertex_element -> Stream = stream_index;
     vertex_element -> Offset = this -> offset;
     vertex_element -> Type = D3DDECLTYPE_FLOAT1;
@@ -239,12 +296,20 @@ void VertexElementArray::add_u_vertex_element (int stream_index)
 void VertexElementArray::add_uv_vertex_element (int stream_index)
 {
   DIRECT_3D_VERTEX_ELEMENT *vertex_element;
+  VERTEX_ELEMENT_TYPE *vertex_element_type;
 
   if (this -> total_elements < this -> maximum_vertex_elements)
   {
     vertex_element = &this -> vertex_element_array [this -> total_elements];
     memset (vertex_element, 0, sizeof (DIRECT_3D_VERTEX_ELEMENT));
 
+    vertex_element_type = &this -> vertex_element_type_array [this -> total_elements];
+    memset (vertex_element_type, 0, sizeof (VERTEX_ELEMENT_TYPE));
+
+    vertex_element_type -> id = VS_TEXTURE_UV;
+    vertex_element_type -> index = vertex_element_type_counter_array [vertex_element_type -> id];
+    vertex_element_type_counter_array [vertex_element_type -> id]++;
+
     vertex_element -> Stream = stream_index;
     vertex_element -> Offset = this -> offset;
     vertex_element -> Type = D3DDECLTYPE_FLOAT2;
@@ -261,12 +326,20 @@ void VertexElementArray::add_uv_vertex_element (int stream_index)
 void VertexElementArray::add_uvw_vertex_element (int stream_index)
 {
   DIRECT_3D_VERTEX_ELEMENT *vertex_element;
+  VERTEX_ELEMENT_TYPE *vertex_element_type;
 
   if (this -> total_elements < this -> maximum_vertex_elements)
   {
     vertex_element = &this -> vertex_element_array [this -> total_elements];
     memset (vertex_element, 0, sizeof (DIRECT_3D_VERTEX_ELEMENT));
 
+    vertex_element_type = &this -> vertex_element_type_array [this -> total_elements];
+    memset (vertex_element_type, 0, sizeof (VERTEX_ELEMENT_TYPE));
+
+    vertex_element_type -> id = VS_TEXTURE_UVW;
+    vertex_element_type -> index = vertex_element_type_counter_array [vertex_element_type -> id];
+    vertex_element_type_counter_array [vertex_element_type -> id]++;
+
     vertex_element -> Stream = stream_index;
     vertex_element -> Offset = this -> offset;
     vertex_element -> Type = D3DDECLTYPE_FLOAT3;
@@ -284,6 +357,7 @@ int VertexElementArray::add_end_vertex_element (void)
 {
   int add;
   DIRECT_3D_VERTEX_ELEMENT *vertex_element;
+  VERTEX_ELEMENT_TYPE *vertex_element_type;
 
   add = FALSE;
   if (this -> total_elements < this -> maximum_vertex_elements)
@@ -291,6 +365,11 @@ int VertexElementArray::add_end_vertex_element (void)
     vertex_element = &this -> vertex_element_array [this -> total_elements];
     memset (vertex_element, 0, sizeof (DIRECT_3D_VERTEX_ELEMENT));
 
+    vertex_element_type = &this -> vertex_element_type_array [this -> total_elements];
+    memset (vertex_element_type, 0, sizeof (VERTEX_ELEMENT_TYPE));
+
+    vertex_element_type -> id = VS_END;
+
     vertex_element -> Stream = 0xFF;
     vertex_element -> Type = D3DDECLTYPE_UNUSED;
 
@@ -317,40 +396,37 @@ CLP(ShaderContext)(ShaderExpansion *s, GSG *gsg) : ShaderContext(s) {
 
   _state = false;
 
-//  _cg_context = (CGcontext)0;
   _cg_profile[SHADER_type_vert] = CG_PROFILE_UNKNOWN;
   _cg_profile[SHADER_type_frag] = CG_PROFILE_UNKNOWN;
   _cg_program[SHADER_type_vert] = (CGprogram)0;
   _cg_program[SHADER_type_frag] = (CGprogram)0;
 
   _vertex_size = 0;
-  _direct_3d_vertex_declaration = 0;
+  _vertex_element_array = 0;
 
   if (header == "//Cg") {
 
     // CGcontext is created once during Reset ( )
-
     if (gsg -> _cg_context == 0) {
       release_resources();
       cerr << "Cg not supported by this video card.\n";
       return;
     }
 
-
-// IGNORE THIS FOR NOW, SEEMS TO BE LOADING IN GL SPECIFIC PROFILES
-if (false)
-{
-    // Parse any directives in the source.
-    string directive;
-    while (!s->parse_eof()) {
-      s->parse_line(directive, true, true);
-      vector_string pieces;
-      tokenize(directive, pieces, " \t");
-      if ((pieces.size()==4)&&(pieces[0]=="//Cg")&&(pieces[1]=="profile")) {
-        suggest_cg_profile(pieces[2], pieces[3]);
+    // IGNORE THIS FOR NOW, SEEMS TO BE LOADING IN GL SPECIFIC PROFILES
+    if (false)
+    {
+      // Parse any directives in the source.
+      string directive;
+      while (!s->parse_eof()) {
+        s->parse_line(directive, true, true);
+        vector_string pieces;
+        tokenize(directive, pieces, " \t");
+        if ((pieces.size()==4)&&(pieces[0]=="//Cg")&&(pieces[1]=="profile")) {
+          suggest_cg_profile(pieces[2], pieces[3]);
+        }
       }
     }
-}
 
     // Select a profile if no preferred profile specified in the source.
     if (_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN) {
@@ -379,6 +455,22 @@ if (false)
   cerr << s->get_name() << ": unrecognized shader language " << header << "\n";
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DXShaderContext9::Destructor
+//       Access: Public
+//  Description: xyz
+////////////////////////////////////////////////////////////////////
+CLP(ShaderContext)::
+~CLP(ShaderContext)() {
+  release_resources();
+
+  if (_vertex_element_array)
+  {
+    delete _vertex_element_array;
+    _vertex_element_array = 0;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DXShaderContext9::suggest_cg_profile
 //       Access: Private
@@ -588,21 +680,6 @@ try_cg_compile(ShaderExpansion *s, GSG *gsg)
 }
 #endif
 
-////////////////////////////////////////////////////////////////////
-//     Function: DXShaderContext9::Destructor
-//       Access: Public
-//  Description: xyz
-////////////////////////////////////////////////////////////////////
-CLP(ShaderContext)::
-~CLP(ShaderContext)() {
-  release_resources();
-
-  if (_direct_3d_vertex_declaration) {
-    _direct_3d_vertex_declaration -> Release ( );
-    _direct_3d_vertex_declaration = 0;
-  }
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: DXShaderContext9::release_resources
 //       Access: Public
@@ -644,47 +721,51 @@ bind(GSG *gsg) {
     HRESULT hr;
 
     // Bind the shaders.
-// ?????    cgD3D9EnableProfile(_cg_profile[SHADER_type_vert]);
     hr = cgD3D9BindProgram(_cg_program[SHADER_type_vert]);
-    if (FAILED (hr)) {
-      dxgsg9_cat.error()
-        << "cgD3D9BindProgram vertex shader failed\n";
+    if (FAILED (hr))
+    {
+      dxgsg9_cat.error() << "cgD3D9BindProgram vertex shader failed\n";
     }
-// ?????    cgD3D9EnableProfile(_cg_profile[SHADER_type_frag]);
     hr = cgD3D9BindProgram(_cg_program[SHADER_type_frag]);
-    if (FAILED (hr)) {
-      dxgsg9_cat.error()
-        << "cgD3D9BindProgram pixel shader failed\n";
+    if (FAILED (hr))
+    {
+      dxgsg9_cat.error() << "cgD3D9BindProgram pixel shader failed\n";
     }
 
+    // DEBUG
+    DBG_SH1
 
-    IDirect3DVertexShader9 *vertex_shader;
-    IDirect3DPixelShader9 *pixel_shader;
+      IDirect3DVertexShader9 *vertex_shader;
+      IDirect3DPixelShader9 *pixel_shader;
 
-    hr = gsg -> _d3d_device -> GetVertexShader (&vertex_shader);
-    if (FAILED (hr)) {
-      dxgsg9_cat.error()
-        << "GetVertexShader ( ) failed "
-        << D3DERRORSTRING(hr);
-    }
-    hr = gsg -> _d3d_device -> GetPixelShader (&pixel_shader);
-    if (FAILED (hr)) {
-      dxgsg9_cat.error()
-        << "GetPixelShader ( ) failed "
-        << D3DERRORSTRING(hr);
-    }
+      hr = gsg -> _d3d_device -> GetVertexShader (&vertex_shader);
+      if (FAILED (hr))
+      {
+        dxgsg9_cat.error()
+          << "GetVertexShader ( ) failed "
+          << D3DERRORSTRING(hr);
+      }
+      hr = gsg -> _d3d_device -> GetPixelShader (&pixel_shader);
+      if (FAILED (hr))
+      {
+        dxgsg9_cat.error()
+          << "GetPixelShader ( ) failed "
+          << D3DERRORSTRING(hr);
+      }
+
+      DBG_SH5  dxgsg9_cat.debug ( )
+        << this -> _name
+        << "\nSHADER: V "
+        << vertex_shader
+        << " P "
+        << pixel_shader
+        << " CG VS"
+        << _cg_program[SHADER_type_vert]
+        << " CG PS"
+        << _cg_program[SHADER_type_frag]
+        << "\n";
+      DBG_E
 
-    DBG_SH5  dxgsg9_cat.debug ( )
-      << this -> _name
-      << "\nSHADER: V "
-      << vertex_shader
-      << " P "
-      << pixel_shader
-      << " CG VS"
-      << _cg_program[SHADER_type_vert]
-      << " CG PS"
-      << _cg_program[SHADER_type_frag]
-      << "\n";
     DBG_E
   }
 #endif
@@ -700,25 +781,21 @@ unbind(GSG *gsg)
 {
 #ifdef HAVE_CGDX9
   if (gsg -> _cg_context != 0) {
-// ?????    cgD3D9DisableProfile(_cg_profile[SHADER_type_vert]);
-// ?????    cgD3D9DisableProfile(_cg_profile[SHADER_type_frag]);
+
+    DBG_SH5  dxgsg9_cat.debug ( ) << "SHADER: unbind \n"; DBG_E
+
     HRESULT hr;
 
     hr = gsg -> _d3d_device -> SetVertexShader (NULL);
     if (FAILED (hr)) {
       dxgsg9_cat.error()
-        << "SetVertexShader (NULL) failed "
-        << D3DERRORSTRING(hr);
+        << "SetVertexShader (NULL) failed " << D3DERRORSTRING(hr);
     }
     hr = gsg -> _d3d_device -> SetPixelShader (NULL);
     if (FAILED (hr)) {
       dxgsg9_cat.error()
-        << "SetPixelShader (NULL) failed "
-        << D3DERRORSTRING(hr);
+        << "SetPixelShader (NULL) failed " << D3DERRORSTRING(hr);
     }
-
-    DBG_SH5  dxgsg9_cat.debug ( ) << "SHADER: unbind \n"; DBG_E
-
   }
 #endif
 }
@@ -760,7 +837,8 @@ issue_cg_auto_bind(const ShaderAutoBind &bind, GSG *gsg)
   case SIC_tps_modelproj:
   case SIC_itp_modelproj:
 
-//    cgGLetStateMatrixParameter(p, (cgD3D9enum)((bind.value >> 2)+4), (cgD3D9enum)(bind.value & 3));
+// ORIGINAL OpenGL CODE
+// cgGLetStateMatrixParameter(p, (cgD3D9enum)((bind.value >> 2)+4), (cgD3D9enum)(bind.value & 3));
 
     const LMatrix4f *p_matrix;
 
@@ -796,7 +874,7 @@ p_matrix = &(gsg -> _internal_transform -> get_mat ( ));
         tex_matrix_attrib = gsg->_state._tex_matrix;
 
 // SHADER ISSUE: using default ????? GL texture matrix = which DX texture matrix ?????
-p_matrix = &(tex_matrix_attrib -> get_mat ( ));
+        p_matrix = &(tex_matrix_attrib -> get_mat ( ));
 
 // SHADER ISSUE: ***** DX_TRANSPOSE REQUIRED FOR COMPATIBILITY
         temp_matrix.transpose_from (*p_matrix);
@@ -808,7 +886,7 @@ p_matrix = &(tex_matrix_attrib -> get_mat ( ));
         const LMatrix4f *model_matrix;
         const LMatrix4f *projection_matrix;
 
-DBG_SH4  dxgsg9_cat.debug ( ) << "SHADER: issue_cg_auto_bind CG_GL_MODELVIEW_PROJECTION_MATRIX " << bind.value << "\n"; DBG_E
+        DBG_SH4  dxgsg9_cat.debug ( ) << "SHADER: issue_cg_auto_bind CG_GL_MODELVIEW_PROJECTION_MATRIX " << bind.value << "\n"; DBG_E
 
         projection_matrix = &gsg->_projection_mat;
 
@@ -1000,17 +1078,33 @@ issue_parameters(GSG *gsg)
 {
 #ifdef HAVE_CGDX9
 
-DBG_SH3  dxgsg9_cat.debug ( ) << "SHADER: issue_parameters\n"; DBG_E
+  DBG_SH3  dxgsg9_cat.debug ( ) << "SHADER: issue_parameters\n"; DBG_E
 
   if (gsg -> _cg_context != 0) {
     // Pass in k-float parameters.
     for (int i=0; i<(int)_cg_fbind.size(); i++) {
+      const float *data;
       InternalName *id = _cg_fbind[i].name;
       const ShaderInput *input = gsg->_target._shader->get_shader_input(id);
 
-DBG_SH3  dxgsg9_cat.debug ( ) << "SHADER: issue_parameters, _cg_fbind " << id -> get_name ( ) << "\n"; DBG_E
+      DBG_SH3  dxgsg9_cat.debug ( ) << "SHADER: issue_parameters, _cg_fbind " << id -> get_name ( ) << "\n"; DBG_E
 
-      cgD3D9SetUniform (_cg_fbind[i].parameter, input->get_vector().get_data());
+      data = input->get_vector().get_data();
+
+      DBG_SH3
+        char string [256];
+
+        sprintf (string, "%f  %f  %f  %f \n", data [0], data [1], data [2], data [3]);
+        dxgsg9_cat.debug ( ) << string;
+      DBG_E
+
+      HRESULT hr;
+
+      hr = cgD3D9SetUniform (_cg_fbind[i].parameter, data);
+      if (FAILED (hr))
+      {
+        dxgsg9_cat.error() << "cgD3D9SetUniform failed " << D3DERRORSTRING(hr);
+      }
     }
 
     // Pass in k-float4x4 parameters.
@@ -1021,7 +1115,7 @@ DBG_SH3  dxgsg9_cat.debug ( ) << "SHADER: issue_parameters, _cg_fbind " << id ->
       if (input->get_nodepath().is_empty()) {
         dat = LMatrix4f::ident_mat().get_data();
 
-DBG_SH3  dxgsg9_cat.debug ( ) << "SHADER: issue_parameters, _cg_npbind " << id -> get_name ( ) << "\n"; DBG_E
+        DBG_SH3  dxgsg9_cat.debug ( ) << "SHADER: issue_parameters, _cg_npbind " << id -> get_name ( ) << "\n"; DBG_E
 
         cgD3D9SetUniform (_cg_npbind[i].parameter, dat);
 
@@ -1047,7 +1141,7 @@ DBG_SH3  dxgsg9_cat.debug ( ) << "SHADER: issue_parameters, _cg_npbind " << id -
         matrix [14] = dat[11];
         matrix [15] = dat[15];
 
-DBG_SH3  dxgsg9_cat.debug ( ) << "SHADER: issue_parameters, _cg_npbind 2 \n"; DBG_E
+        DBG_SH3  dxgsg9_cat.debug ( ) << "SHADER: issue_parameters, _cg_npbind 2 \n"; DBG_E
 
         cgD3D9SetUniform (_cg_npbind[i].parameter, matrix);
       }
@@ -1061,7 +1155,7 @@ DBG_SH3  dxgsg9_cat.debug ( ) << "SHADER: issue_parameters, _cg_npbind 2 \n"; DB
     // Pass in trans,tpose,row,col,xvec,yvec,zvec,pos parameters
     for (int i=0; i<(int)_cg_parameter_bind.size(); i++) {
 
-DBG_SH3  dxgsg9_cat.debug ( ) << "SHADER: issue_parameters, _cg_parameter_bind \n"; DBG_E
+      DBG_SH3  dxgsg9_cat.debug ( ) << "SHADER: issue_parameters, _cg_parameter_bind \n"; DBG_E
 
       bind_cg_transform(_cg_parameter_bind[i], gsg);
     }
@@ -1133,8 +1227,6 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
 #ifdef HAVE_CGDX9
   if (gsg -> _cg_context) {
 
-    HRESULT hr;
-
 /* ?????
 #ifdef SUPPORT_IMMEDIATE_MODE
     if (gsg->_use_sender) {
@@ -1143,18 +1235,19 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
 #endif // SUPPORT_IMMEDIATE_MODE
 */
 
-// map the vertex shader inputs into a DirectX vertex declaration
-// create and cache the vertex declaration
-// this can be done here since a vertex shader has a fixed input
-
-    if (_direct_3d_vertex_declaration == 0) {
-
+    // Create and cache a VertexElementArray that does most of the
+    // mapping from the vertex shader inputs to a VertexElementArray.
+    // This can be done since a vertex shader has a well defined input.
+    // Later when the vertex buffer is applied the offsets will
+    // be properly mapped.
+    if (_vertex_element_array == 0)
+    {
       const GeomVertexArrayData *array_data;
       Geom::NumericType numeric_type;
       int start, stride, num_values;
       int nvarying = _cg_varying.size();
 
-DBG_SH1  dxgsg9_cat.debug ( ) << "SHADER: update_shader_vertex_arrays: nvarying " << nvarying <<  "\n"; DBG_E
+      DBG_SH1  dxgsg9_cat.debug ( ) << "SHADER: update_shader_vertex_arrays: nvarying = " << nvarying <<  "\n"; DBG_E
 
       int stream_index;
       VertexElementArray *vertex_element_array;
@@ -1179,127 +1272,127 @@ DBG_SH1  dxgsg9_cat.debug ( ) << "SHADER: update_shader_vertex_arrays: nvarying
             }
           }
         }
-        if (gsg->_vertex_data->get_array_info(name, array_data, num_values,
-              numeric_type, start, stride)) {
-
-if (false) {
-
-} else if (name == InternalName::get_vertex ( )) {
-
-  if (numeric_type == Geom::NT_float32) {
-    switch (num_values) {
-      case 3:
-        vertex_element_array -> add_position_xyz_vertex_element (stream_index);
-        break;
-      default:
-        dxgsg9_cat.error ( ) << "VERTEX ERROR: invalid number of vertex coordinate elements " << num_values << "\n";
-        break;
-    }
-  } else {
-    dxgsg9_cat.error ( ) << "VERTEX ERROR: invalid vertex type " << numeric_type << "\n";
-  }
-
-} else if (name == InternalName::get_texcoord ( )) {
-
-  if (numeric_type == Geom::NT_float32) {
-    switch (num_values)
-    {
-      case 1:
-        vertex_element_array -> add_u_vertex_element (stream_index);
-        break;
-      case 2:
-        vertex_element_array -> add_uv_vertex_element (stream_index);
-        break;
-      case 3:
-        vertex_element_array -> add_uvw_vertex_element (stream_index);
-        break;
-      default:
-        dxgsg9_cat.error ( ) << "VERTEX ERROR: invalid number of vertex texture coordinate elements " << num_values <<  "\n";
-        break;
-    }
-  } else {
-    dxgsg9_cat.error ( ) << "VERTEX ERROR: invalid texture coordinate type " << numeric_type << "\n";
-  }
-
-} else if (name == InternalName::get_normal ( )) {
-
-  if (numeric_type == Geom::NT_float32) {
-    switch (num_values)
-    {
-      case 3:
-        vertex_element_array -> add_normal_vertex_element (stream_index);
-        break;
-      default:
-        dxgsg9_cat.error ( ) << "VERTEX ERROR: invalid number of normal coordinate elements " << num_values <<  "\n";
-        break;
-    }
-  } else {
-    dxgsg9_cat.error ( ) << "VERTEX ERROR: invalid normal type " << numeric_type << "\n";
-  }
-
-} else if (name == InternalName::get_binormal ( )) {
-
-  if (numeric_type == Geom::NT_float32) {
-    switch (num_values)
-    {
-      case 3:
-        vertex_element_array -> add_binormal_vertex_element (stream_index);
-        break;
-      default:
-        dxgsg9_cat.error ( ) << "VERTEX ERROR: invalid number of binormal coordinate elements " << num_values <<  "\n";
-        break;
-    }
-  } else {
-    dxgsg9_cat.error ( ) << "VERTEX ERROR: invalid binormal type " << numeric_type << "\n";
-  }
-
-} else if (name == InternalName::get_tangent ( )) {
-
-  if (numeric_type == Geom::NT_float32) {
-    switch (num_values)
-    {
-      case 3:
-        vertex_element_array -> add_tangent_vertex_element (stream_index);
-        break;
-      default:
-        dxgsg9_cat.error ( ) << "VERTEX ERROR: invalid number of tangent coordinate elements " << num_values <<  "\n";
-        break;
-    }
-  } else {
-    dxgsg9_cat.error ( ) << "VERTEX ERROR: invalid tangent type " << numeric_type << "\n";
-  }
+        if (gsg->_vertex_data->get_array_info(name, array_data, num_values, numeric_type, start, stride))
+        {
+/*
+          // ORIGINAL OpenGL CODE
+          const unsigned char *client_pointer = gsg->setup_array_data(array_data);
+          cgGLSetParameterPointer(_cg_varying[i].parameter,
+                                  num_values, gsg->get_numeric_type(numeric_type),
+                                  stride, client_pointer + start);
+*/
 
-} else if (name == InternalName::get_color ( )) {
+          if (false) {
+
+          } else if (name == InternalName::get_vertex ( )) {
+
+            if (numeric_type == Geom::NT_float32) {
+              switch (num_values) {
+                case 3:
+                  vertex_element_array -> add_position_xyz_vertex_element (stream_index);
+                  break;
+                case 4:
+                  vertex_element_array -> add_position_xyzw_vertex_element (stream_index);
+                  break;
+                default:
+                  dxgsg9_cat.error ( ) << "VE ERROR: invalid number of vertex coordinate elements " << num_values << "\n";
+                  break;
+              }
+            } else {
+              dxgsg9_cat.error ( ) << "VE ERROR: invalid vertex type " << numeric_type << "\n";
+            }
 
-  if (numeric_type == Geom::NT_packed_dcba || numeric_type == Geom::NT_packed_dabc) {
-    switch (num_values)
-    {
-      case 4:
-        vertex_element_array -> add_diffuse_color_vertex_element (stream_index);
-        break;
-      default:
-        dxgsg9_cat.error ( ) << "VERTEX ERROR: invalid color coordinates " << num_values <<  "\n";
-        break;
-    }
-  } else {
-    dxgsg9_cat.error ( ) << "VERTEX ERROR: invalid color type " << numeric_type << "\n";
-  }
+          } else if (name == InternalName::get_texcoord ( )) {
+
+            if (numeric_type == Geom::NT_float32) {
+              switch (num_values)
+              {
+                case 1:
+                  vertex_element_array -> add_u_vertex_element (stream_index);
+                  break;
+                case 2:
+                  vertex_element_array -> add_uv_vertex_element (stream_index);
+                  break;
+                case 3:
+                  vertex_element_array -> add_uvw_vertex_element (stream_index);
+                  break;
+                default:
+                  dxgsg9_cat.error ( ) << "VE ERROR: invalid number of vertex texture coordinate elements " << num_values <<  "\n";
+                  break;
+              }
+            } else {
+              dxgsg9_cat.error ( ) << "VE ERROR: invalid texture coordinate type " << numeric_type << "\n";
+            }
 
-} else {
-  dxgsg9_cat.error ( ) << "VERTEX ERROR: unsupported vertex element " << name -> get_name ( ) <<  "\n";
-}
+          } else if (name == InternalName::get_normal ( )) {
+
+            if (numeric_type == Geom::NT_float32) {
+              switch (num_values)
+              {
+                case 3:
+                  vertex_element_array -> add_normal_vertex_element (stream_index);
+                  break;
+                default:
+                  dxgsg9_cat.error ( ) << "VE ERROR: invalid number of normal coordinate elements " << num_values << "\n";
+                  break;
+              }
+            } else {
+              dxgsg9_cat.error ( ) << "VE ERROR: invalid normal type " << numeric_type << "\n";
+            }
 
+          } else if (name == InternalName::get_binormal ( )) {
+
+            if (numeric_type == Geom::NT_float32) {
+              switch (num_values)
+              {
+                case 3:
+                  vertex_element_array -> add_binormal_vertex_element (stream_index);
+                  break;
+                default:
+                  dxgsg9_cat.error ( ) << "VE ERROR: invalid number of binormal coordinate elements " << num_values << "\n";
+                  break;
+              }
+            } else {
+              dxgsg9_cat.error ( ) << "VE ERROR: invalid binormal type " << numeric_type << "\n";
+            }
 
-// ?????
-/*
+          } else if (name == InternalName::get_tangent ( )) {
+
+            if (numeric_type == Geom::NT_float32) {
+              switch (num_values)
+              {
+                case 3:
+                  vertex_element_array -> add_tangent_vertex_element (stream_index);
+                  break;
+                default:
+                  dxgsg9_cat.error ( ) << "VE ERROR: invalid number of tangent coordinate elements " << num_values << "\n";
+                  break;
+              }
+            } else {
+              dxgsg9_cat.error ( ) << "VE ERROR: invalid tangent type " << numeric_type << "\n";
+            }
 
-gsg->_vertex_data;
+          } else if (name == InternalName::get_color ( )) {
+
+            if (numeric_type == Geom::NT_packed_dcba ||
+                numeric_type == Geom::NT_packed_dabc ||
+                numeric_type == Geom::NT_uint8) {
+              switch (num_values)
+              {
+                case 4:
+                  vertex_element_array -> add_diffuse_color_vertex_element (stream_index);
+                  break;
+                default:
+                  dxgsg9_cat.error ( ) << "VE ERROR: invalid color coordinates " << num_values << "\n";
+                  break;
+              }
+            } else {
+              dxgsg9_cat.error ( ) << "VE ERROR: invalid color type " << numeric_type << "\n";
+            }
 
-          const unsigned char *client_pointer = gsg->setup_array_data(array_data);
-          cgD3D9SetParameterPointer(_cg_varying[i].parameter,
-                                  num_values, gsg->get_numeric_type(numeric_type),
-                                  stride, client_pointer + start);
-*/
+          } else {
+            dxgsg9_cat.error ( ) << "VE ERROR: unsupported vertex element " << name -> get_name ( ) << "\n";
+          }
 
           DBG_SH1  dxgsg9_cat.debug ( ) << "SHADER: update_shader_vertex_arrays " << i <<  "\n"; DBG_E
           DBG_SH1  dxgsg9_cat.debug ( )
@@ -1311,74 +1404,37 @@ gsg->_vertex_data;
             << "\n"; DBG_E
 
         } else {
-
+          dxgsg9_cat.error ( ) << "get_array_info ( ) failed\n";
         }
       }
 
       int state;
 
       state = vertex_element_array -> add_end_vertex_element ( );
-
-      if (vertex_element_array) {
-        HRESULT hr;
-
-        if (state) {
-
-          if (cgD3D9ValidateVertexDeclaration (_cg_program [SHADER_type_vert], vertex_element_array -> vertex_element_array) == CG_TRUE)
-          {
-            dxgsg9_cat.debug() << "||||| cgD3D9ValidateVertexDeclaration succeeded\n";
-          }
-          else
-          {
-            dxgsg9_cat.error() << "********************************************\n";
-            dxgsg9_cat.error() << "***cgD3D9ValidateVertexDeclaration failed***\n";
-            dxgsg9_cat.error() << "********************************************\n";
-          }
-
-          hr = gsg -> _d3d_device ->CreateVertexDeclaration (vertex_element_array -> vertex_element_array, &_direct_3d_vertex_declaration);
-          if (FAILED (hr)) {
-            dxgsg9_cat.error()
-              << "CreateVertexDeclaration failed"
-              << D3DERRORSTRING(hr);
-          }
-
-          _vertex_size = vertex_element_array -> offset;
-
-          DBG_SH1  dxgsg9_cat.debug ( ) << "SHADER: vertex size " << _vertex_size <<  "\n"; DBG_E
+      if (state)
+      {
+        if (cgD3D9ValidateVertexDeclaration (_cg_program [SHADER_type_vert], vertex_element_array -> vertex_element_array) == CG_TRUE)
+        {
+          dxgsg9_cat.debug() << "|||||cgD3D9ValidateVertexDeclaration succeeded\n";
+        }
+        else
+        {
+          dxgsg9_cat.error() << "********************************************\n";
+          dxgsg9_cat.error() << "***cgD3D9ValidateVertexDeclaration failed***\n";
+          dxgsg9_cat.error() << "********************************************\n";
         }
 
-        delete vertex_element_array;
-      }
-    }
-    if (_direct_3d_vertex_declaration)
-    {
-      hr = gsg -> _d3d_device -> SetVertexDeclaration (_direct_3d_vertex_declaration);
-      if (FAILED(hr)) {
-        dxgsg9_cat.error()
-          << "SetVertexDeclaration failed" << D3DERRORSTRING(hr);
-      } else {
-        DBG_SH5 dxgsg9_cat.debug() << "Shader SetVertexDeclaration ( ) \n"; DBG_E
-      }
-
-/*
-      UINT stream_number;
-      IDirect3DVertexBuffer9 *vertex_buffer;
-      UINT offset;
-      UINT stride;
+        _vertex_size = vertex_element_array -> offset;
 
-      stream_number = 0;
-vertex_buffer = 0;
-      offset = 0;
-      stride = 0;
+        DBG_SH1  dxgsg9_cat.debug ( ) << "SHADER: vertex size " << _vertex_size <<  "\n"; DBG_E
 
-      hr = gsg -> _d3d_device -> SetStreamSource (stream_number, vertex_buffer, offset, stride);
-      if (FAILED (hr)) {
-        dxgsg9_cat.error()
-          << "SetStreamSource failed "
-          << D3DERRORSTRING(hr);
+        _vertex_element_array = vertex_element_array;
+      }
+      else
+      {
+        dxgsg9_cat.error ( ) << "VertexElementArray creation failed\n";
+        delete vertex_element_array;
       }
-*/
-
     }
   }
 #endif // HAVE_CGDX9

+ 3 - 1
panda/src/dxgsg9/dxShaderContext9.h

@@ -37,8 +37,10 @@
 #define CLASSPREFIX_QUOTED "DX"
 
 
+class VertexElementArray;
 class CLP(GraphicsStateGuardian);
 
+
 ////////////////////////////////////////////////////////////////////
 //       Class : DXShaderContext9
 // Description : xyz
@@ -63,7 +65,7 @@ public:
   void update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg);
 
   int _vertex_size;
-  DIRECT_3D_VERTEX_DECLARATION _direct_3d_vertex_declaration;
+  class VertexElementArray *_vertex_element_array;
 
   // FOR DEBUGGING
   string _name;

+ 102 - 4
panda/src/dxgsg9/dxVertexBufferContext9.cxx

@@ -4,7 +4,7 @@
 ////////////////////////////////////////////////////////////////////
 //
 // PANDA 3D SOFTWARE
-// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+// Copyright (c) 2001 - 2006, Disney Enterprises, Inc.  All rights reserved
 //
 // All use of this software is subject to the terms of the Panda 3d
 // Software license.  You should have received a copy of this license
@@ -35,7 +35,7 @@ TypeHandle DXVertexBufferContext9::_type_handle;
 //  Description:
 ////////////////////////////////////////////////////////////////////
 DXVertexBufferContext9::
-DXVertexBufferContext9(GeomVertexArrayData *data) :
+DXVertexBufferContext9(GeomVertexArrayData *data, DXScreenData &scrn) :
   VertexBufferContext(data),
   _vbuffer(NULL)
 {
@@ -44,13 +44,103 @@ DXVertexBufferContext9(GeomVertexArrayData *data) :
 
   // We have to start with the vertex data, and work up from there in
   // order, since that's the way the FVF is defined.
+  int index;
   int n = 0;
   int num_columns = array_format->get_num_columns();
+  int total_elements;
+
+  total_elements = num_columns + 2;
+  _vertex_element_type_array = new VERTEX_ELEMENT_TYPE [total_elements];
+  memset (_vertex_element_type_array, 0, total_elements * sizeof (VERTEX_ELEMENT_TYPE));
+
+  // create a simple vertex type mapping from the vertex elements
+  for (index = 0; index < num_columns; index++)
+  {
+    int num_values;
+    const InternalName *name;
+
+    name = array_format -> get_column (index) -> get_name ( );
+    num_values = array_format -> get_column(index) -> get_num_values ( );
+
+    if (false) {
+
+    } else if (name == InternalName::get_vertex ( )) {
+
+      switch (num_values)
+      {
+        case 3:
+          _vertex_element_type_array [index].id = VS_POSITION_XYZ;
+          break;
+        case 4:
+          _vertex_element_type_array [index].id = VS_POSITION_XYZW;
+          break;
+        default:
+          dxgsg9_cat.error ( ) << "VERTEX ERROR: invalid number of position coordinate elements " << num_values << "\n";
+          break;
+      }
+
+    } else if (name == InternalName::get_texcoord ( )) {
+
+      switch (num_values)
+      {
+        case 1:
+          _vertex_element_type_array [index].id = VS_TEXTURE_U;
+          break;
+        case 2:
+          _vertex_element_type_array [index].id = VS_TEXTURE_UV;
+          break;
+        case 3:
+          _vertex_element_type_array [index].id = VS_TEXTURE_UVW;
+          break;
+        default:
+          dxgsg9_cat.error ( ) << "VERTEX ERROR: invalid number of vertex texture coordinate elements " << num_values << "\n";
+          break;
+      }
+
+    } else if (name == InternalName::get_normal ( )) {
+
+      _vertex_element_type_array [index].id = VS_NORMAL;
+
+    } else if (name == InternalName::get_binormal ( )) {
+
+      _vertex_element_type_array [index].id = VS_BINORMAL;
+
+    } else if (name == InternalName::get_tangent ( )) {
+
+      _vertex_element_type_array [index].id = VS_TANGENT;
+
+    } else if (name == InternalName::get_color ( )) {
+
+      _vertex_element_type_array [index].id = VS_DIFFUSE;
+
+    } else {
+
+      dxgsg9_cat.error ( ) << "VERTEX ERROR: unsupported vertex element " << name -> get_name ( ) << "\n";
+      _vertex_element_type_array [index].id = VS_ERROR;
+    }
+
+// SHADER ISSUE: STREAM INDEX ALWAYS 0 FOR VERTEX BUFFER ???
+    _vertex_element_type_array [index].stream = 0;
+    _vertex_element_type_array [index].offset = array_format -> get_column(index) -> get_start ( );
+
+    DBG_VEA  dxgsg9_cat.debug() << "INFO VertexElementArray " << index
+      << " " << name -> get_name ( )
+      << " VS ID " << _vertex_element_type_array [index].id
+      << " offset " << _vertex_element_type_array [index].offset
+      << "\n";
+    DBG_E
+  }
+
+  DBG_VEA  dxgsg9_cat.debug() << "INFO stride " << array_format -> get_stride ( ) << " total bytes " << array_format-> get_total_bytes ( ) << "\n"; DBG_E
+
 
   _fvf = 0;
   _managed = -1;
   _lru_page = 0;
 
+  _direct_3d_vertex_declaration = 0;
+  _shader_context = 0;
+
   if (n < num_columns &&
       array_format->get_column(n)->get_name() == InternalName::get_vertex()) {
     ++n;
@@ -175,10 +265,18 @@ DXVertexBufferContext9(GeomVertexArrayData *data) :
 DXVertexBufferContext9::
 ~DXVertexBufferContext9() {
 
+  if (_vertex_element_type_array) {
+    delete _vertex_element_type_array;
+    _vertex_element_type_array = 0;
+  }
+  if (_direct_3d_vertex_declaration) {
+    _direct_3d_vertex_declaration -> Release ( );
+    _direct_3d_vertex_declaration = 0;
+  }
+
   free_vbuffer ( );
 
-  if (_lru_page)
-  {
+  if (_lru_page) {
     _lru_page -> _m.lru -> remove_page (_lru_page);
     _lru_page -> _m.lru -> free_page (_lru_page);
     _lru_page = 0;

+ 6 - 1
panda/src/dxgsg9/dxVertexBufferContext9.h

@@ -30,7 +30,7 @@
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDADX DXVertexBufferContext9 : public VertexBufferContext {
 public:
-  DXVertexBufferContext9(GeomVertexArrayData *data);
+  DXVertexBufferContext9(GeomVertexArrayData *data, DXScreenData &scrn);
   virtual ~DXVertexBufferContext9();
 
   void free_vbuffer(void);
@@ -40,9 +40,14 @@ public:
 
   IDirect3DVertexBuffer9 *_vbuffer;
   int _fvf;
+
   int _managed;
   LruPage *_lru_page;
 
+  VERTEX_ELEMENT_TYPE *_vertex_element_type_array;
+  DIRECT_3D_VERTEX_DECLARATION _direct_3d_vertex_declaration;
+  CLP(ShaderContext) *_shader_context;
+
 public:
   static TypeHandle get_class_type() {
     return _type_handle;

+ 2 - 1
panda/src/dxgsg9/dxgsg9_composite1.cxx

@@ -1,5 +1,5 @@
 #include "dxgsg9base.h"
-#include "wdxGraphicsBuffer9.cxx"
+#include "dxShaderContext9.cxx"
 #include "config_dxgsg9.cxx"
 #include "dxTextureContext9.cxx"
 #include "dxVertexBufferContext9.cxx"
@@ -8,4 +8,5 @@
 #include "wdxGraphicsPipe9.cxx"
 #include "wdxGraphicsWindow9.cxx"
 #include "dxGraphicsDevice9.cxx"
+#include "wdxGraphicsBuffer9.cxx"
 

+ 1 - 1
panda/src/dxgsg9/dxgsg9base.h

@@ -93,7 +93,7 @@ typedef DWORD DXShaderHandle;
 
 
 // uncomment to add refcnt debug output
-#define DEBUG_RELEASES
+// #define DEBUG_RELEASES
 
 #ifdef DEBUG_RELEASES
 #define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero)             {  \

+ 8 - 10
panda/src/dxgsg9/wdxGraphicsBuffer9.cxx

@@ -4,7 +4,7 @@
 ////////////////////////////////////////////////////////////////////
 //
 // PANDA 3D SOFTWARE
-// Copyright (c) 2001 - 2005, Disney Enterprises, Inc.  All rights reserved
+// Copyright (c) 2001 - 2006, Disney Enterprises, Inc.  All rights reserved
 //
 // All use of this software is subject to the terms of the Panda 3d
 // Software license.  You should have received a copy of this license
@@ -27,8 +27,6 @@
   // support copy from texture to ram?
     // check D3DCAPS2_DYNAMICTEXTURES
 
-#define DBG_S if (false) {
-#define DBG_E }
 #define FL << "\n" << __FILE__ << " " << __LINE__ << "\n"
 
 TypeHandle wdxGraphicsBuffer9::_type_handle;
@@ -84,7 +82,7 @@ begin_frame() {
     return false;
   }
 
-DBG_S dxgsg9_cat.error ( ) << "wdxGraphicsBuffer9::begin_frame\n"; DBG_E
+  DBG_S dxgsg9_cat.debug ( ) << "wdxGraphicsBuffer9::begin_frame\n"; DBG_E
 
   DXGraphicsStateGuardian9 *dxgsg;
   DCAST_INTO_R(dxgsg, _gsg, false);
@@ -116,7 +114,7 @@ begin_render_texture() {
     state = false;
     render_target_index = 0;
 
-DBG_S dxgsg9_cat.error ( ) << "wdxGraphicsBuffer9::begin_render_texture\n"; DBG_E
+    DBG_S dxgsg9_cat.debug ( ) << "wdxGraphicsBuffer9::begin_render_texture\n"; DBG_E
 
     if (dxgsg -> _d3d_device) {
       Texture *tex = get_texture(0);
@@ -207,7 +205,7 @@ DBG_S dxgsg9_cat.error ( ) << "wdxGraphicsBuffer9::begin_render_texture\n"; DBG_
 void wdxGraphicsBuffer9::
 end_render_texture() {
 
-DBG_S dxgsg9_cat.error ( ) << "wdxGraphicsBuffer9::end_render_texture\n"; DBG_E
+DBG_S dxgsg9_cat.debug ( ) << "wdxGraphicsBuffer9::end_render_texture\n"; DBG_E
 
   if (_gsg != (GraphicsStateGuardian *)NULL) {
 
@@ -315,7 +313,7 @@ select_cube_map(int cube_map_index) {
                 }
               }
 
-DBG_S dxgsg9_cat.error ( ) << "select_cube_map " << _cube_map_index << "\n";  DBG_E
+              DBG_S dxgsg9_cat.debug ( ) << "select_cube_map " << _cube_map_index << "\n";  DBG_E
 
             } else {
               dxgsg9_cat.error ( ) << "SetRenderTarget " << D3DERRORSTRING(hr) FL;
@@ -346,7 +344,7 @@ make_current() {
   DCAST_INTO_V(dxgsg, _gsg);
 
   // do nothing here
-DBG_S dxgsg9_cat.error ( ) << "wdxGraphicsBuffer9::make_current\n"; DBG_E
+  DBG_S dxgsg9_cat.debug ( ) << "wdxGraphicsBuffer9::make_current\n"; DBG_E
 
 }
 
@@ -480,7 +478,7 @@ open_buffer() {
         width = tex -> get_x_size ( );
         height = tex -> get_y_size ( );
 
-DBG_S dxgsg9_cat.error ( ) << "-------------RTT SIZE " << "t width " << width << " t height " << height FL; DBG_E
+        DBG_S dxgsg9_cat.debug ( ) << "-------------RTT SIZE " << "t width " << width << " t height " << height FL; DBG_E
 
         if (surface_description.Width < width || surface_description.Height < height) {
           format = surface_description.Format;
@@ -493,7 +491,7 @@ DBG_S dxgsg9_cat.error ( ) << "-------------RTT SIZE " << "t width " << width <<
             discard, &this -> _new_z_stencil_surface, NULL);
           if (SUCCEEDED  (hr)) {
 
-DBG_S dxgsg9_cat.error ( ) << "-------------OK CreatedDepthStencilSurface " << D3DERRORSTRING(hr) FL; DBG_E
+            DBG_S dxgsg9_cat.debug ( ) << "-------------OK CreatedDepthStencilSurface " << D3DERRORSTRING(hr) FL; DBG_E
 
             state = true;