Browse Source

dxgsg9: Reimplement shader support on top of SPIR-V pipeline

rdb 5 years ago
parent
commit
ca5acbb3b5

+ 10 - 2
makepanda/makepanda.py

@@ -760,6 +760,11 @@ if (COMPILER == "MSVC"):
     LibName("SPIRV-CROSS-GLSL", GetThirdpartyDir() + "spirv-cross/lib/spirv-cross-core.lib")
     LibName("SPIRV-CROSS-GLSL", GetThirdpartyDir() + "spirv-cross/lib/spirv-cross-glsl.lib")
 
+    IncDirectory("SPIRV-CROSS-HLSL", GetThirdpartyDir() + "spirv-cross/include")
+    LibName("SPIRV-CROSS-HLSL", GetThirdpartyDir() + "spirv-cross/lib/spirv-cross-core.lib")
+    LibName("SPIRV-CROSS-HLSL", GetThirdpartyDir() + "spirv-cross/lib/spirv-cross-hlsl.lib")
+    LibName("SPIRV-CROSS-HLSL", GetThirdpartyDir() + "spirv-cross/lib/spirv-cross-glsl.lib") # sic
+
 if (COMPILER=="GCC"):
     if GetTarget() != "darwin":
         PkgDisable("COCOA")
@@ -818,6 +823,7 @@ if (COMPILER=="GCC"):
     SmartPkgEnable("GLSLANG",   "",          ("glslang", "SPIRV", "OSDependent", "OGLCompiler", "HLSL"), "glslang/Public/ShaderLang.h")
     SmartPkgEnable("SPIRV-TOOLS", "",        ("SPIRV-Tools", "SPIRV-Tools-opt"), "spirv-tools/optimizer.hpp")
     SmartPkgEnable("SPIRV-CROSS-GLSL", "",   ("spirv-cross-core", "spirv-cross-glsl"), "spirv_cross/spirv_cross.hpp")
+    SmartPkgEnable("SPIRV-CROSS-HLSL", "",   ("spirv-cross-core", "spirv-cross-hlsl"), "spirv_cross/spirv_cross.hpp")
 
     # Copy freetype libraries to be specified after harfbuzz libraries as well,
     # because there's a circular dependency between the two libraries.
@@ -898,6 +904,8 @@ if (COMPILER=="GCC"):
 
         LibName("SPIRV-CROSS-GLSL", "-Wl,--exclude-libs,libspirv-cross-core.a")
         LibName("SPIRV-CROSS-GLSL", "-Wl,--exclude-libs,libspirv-cross-glsl.a")
+        LibName("SPIRV-CROSS-HLSL", "-Wl,--exclude-libs,libspirv-cross-core.a")
+        LibName("SPIRV-CROSS-HLSL", "-Wl,--exclude-libs,libspirv-cross-hlsl.a")
 
     if PkgSkip("FFMPEG") or GetTarget() == "darwin":
         cv_lib = ChooseLib(("opencv_core", "cv"), "OPENCV")
@@ -4359,7 +4367,7 @@ if (GetTarget() == 'windows'):
 #
 
 if GetTarget() == 'windows' and PkgSkip("DX9")==0:
-  OPTS=['DIR:panda/src/dxgsg9', 'BUILDING:PANDADX', 'DX9',  'NVIDIACG', 'CGDX9']
+  OPTS=['DIR:panda/src/dxgsg9', 'BUILDING:PANDADX', 'DX9',  'NVIDIACG', 'CGDX9', 'SPIRV-CROSS-HLSL']
   TargetAdd('p3dxgsg9_dxGraphicsStateGuardian9.obj', opts=OPTS, input='dxGraphicsStateGuardian9.cxx')
   TargetAdd('p3dxgsg9_composite1.obj', opts=OPTS, input='p3dxgsg9_composite1.cxx')
   OPTS=['DIR:panda/metalibs/pandadx9', 'BUILDING:PANDADX', 'DX9',  'NVIDIACG', 'CGDX9']
@@ -4369,7 +4377,7 @@ if GetTarget() == 'windows' and PkgSkip("DX9")==0:
   TargetAdd('libpandadx9.dll', input='p3dxgsg9_composite1.obj')
   TargetAdd('libpandadx9.dll', input='libp3windisplay.dll')
   TargetAdd('libpandadx9.dll', input=COMMON_PANDA_LIBS)
-  TargetAdd('libpandadx9.dll', opts=['MODULE', 'ADVAPI', 'WINGDI', 'WINKERNEL', 'WINUSER', 'WINMM', 'DX9',  'NVIDIACG', 'CGDX9'])
+  TargetAdd('libpandadx9.dll', opts=['MODULE', 'ADVAPI', 'WINGDI', 'WINKERNEL', 'WINUSER', 'WINMM', 'DX9',  'NVIDIACG', 'CGDX9', 'SPIRV-CROSS-HLSL'])
 
 #
 # DIRECTORY: panda/src/egg/

+ 83 - 63
panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx

@@ -410,31 +410,8 @@ ShaderContext *DXGraphicsStateGuardian9::
 prepare_shader(Shader *se) {
   PStatTimer timer(_prepare_shader_pcollector);
 
-  switch (se->get_language()) {
-  case Shader::SL_GLSL:
-    dxgsg9_cat.error()
-      << "Tried to load GLSL shader, but GLSL shaders not supported by Direct3D 9.\n";
-    return nullptr;
-
-  case Shader::SL_Cg:
-#ifdef HAVE_CG
-    if (_supports_basic_shaders) {
-      return new DXShaderContext9(se, this);
-    } else {
-      dxgsg9_cat.error()
-        << "Tried to load Cg shader, but basic shaders not supported.\n";
-      return nullptr;
-    }
-#else
-    dxgsg9_cat.error()
-      << "Tried to load Cg shader, but Cg support not compiled in.\n";
-    return nullptr;
-#endif
-
-  default:
-    dxgsg9_cat.error()
-      << "Tried to load shader with unsupported shader language!\n";
-    return nullptr;
+  if (_supports_basic_shaders) {
+    return new DXShaderContext9(se, this);
   }
 
   return nullptr;
@@ -1088,11 +1065,13 @@ void DXGraphicsStateGuardian9::
 end_scene() {
   GraphicsStateGuardian::end_scene();
 
-  if (_vertex_array_shader_context != 0) {
-    _vertex_array_shader_context->disable_shader_vertex_arrays(this);
-    _vertex_array_shader = nullptr;
-    _vertex_array_shader_context = nullptr;
+  // Unbind streams.
+  _d3d_device->SetVertexDeclaration(nullptr);
+  for (int array_index = 0; array_index < _num_bound_streams; ++array_index) {
+    _d3d_device->SetStreamSource(array_index, nullptr, 0, 0);
   }
+  _num_bound_streams = 0;
+
   if (_texture_binding_shader_context != 0) {
     _texture_binding_shader_context->disable_shader_texture_bindings(this);
     _texture_binding_shader = nullptr;
@@ -1187,6 +1166,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
   nassertr(_data_reader != nullptr, false);
 
   const GeomVertexFormat *format = _data_reader->get_format();
+  LPDIRECT3DDEVICE9 device = _d3d_device;
 
   const GeomVertexAnimationSpec &animation =
     data_reader->get_format()->get_animation();
@@ -1225,7 +1205,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
         LMatrix4 mat;
         table->get_transform(i)->mult_matrix(mat, _internal_transform->get_mat());
         const D3DMATRIX *d3d_mat = (const D3DMATRIX *)mat.get_data();
-        _d3d_device->SetTransform(D3DTS_WORLDMATRIX(i), d3d_mat);
+        device->SetTransform(D3DTS_WORLDMATRIX(i), d3d_mat);
       }
 
       // Setting the first animation matrix steps on the world matrix, so we
@@ -1244,7 +1224,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
 
     if (_transform_stale && !_data_reader->is_vertex_transformed()) {
       const D3DMATRIX *d3d_mat = (const D3DMATRIX *)_internal_transform->get_mat().get_data();
-      _d3d_device->SetTransform(D3DTS_WORLD, d3d_mat);
+      device->SetTransform(D3DTS_WORLD, d3d_mat);
       _transform_stale = false;
     }
   }
@@ -1257,7 +1237,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
     // It's tempting just to use the D3DFVF_XYZRHW specification on these
     // vertices, but that turns out to be a bigger hammer than we want: that
     // also prevents lighting calculations and user clip planes.
-    _d3d_device->SetTransform(D3DTS_WORLD, &_d3d_ident_mat);
+    device->SetTransform(D3DTS_WORLD, &_d3d_ident_mat);
     static const LMatrix4f rescale_mat
       (1, 0, 0, 0,
        0, 1, 0, 0,
@@ -1265,34 +1245,70 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
        0, 0, 0.5, 1);
     _transform_stale = true;
 
-    _d3d_device->SetTransform(D3DTS_PROJECTION, (const D3DMATRIX *)rescale_mat.get_data());
+    device->SetTransform(D3DTS_PROJECTION, (const D3DMATRIX *)rescale_mat.get_data());
   }
 
-  if (_current_shader_context == 0 /*|| !_current_shader_context->uses_custom_vertex_arrays()*/) {
-    // No shader, or a non-Cg shader.
-    if (_vertex_array_shader_context != 0) {
-      _vertex_array_shader_context->disable_shader_vertex_arrays(this);
-    }
+  if (_current_shader_context == nullptr) {
+    // No shader.
+    device->SetVertexDeclaration(nullptr);
     if (!update_standard_vertex_arrays(force)) {
       return false;
     }
   } else {
-    // Cg shader.
-    if (_vertex_array_shader_context == 0) {
-      disable_standard_vertex_arrays();
-      if (!_current_shader_context->update_shader_vertex_arrays(nullptr, this, force)) {
-        return false;
+    // Set the vertex declaration for the shader.
+    LPDIRECT3DVERTEXDECLARATION9 decl =
+      _current_shader_context->get_vertex_declaration(this, format);
+    if (decl == nullptr) {
+      return false;
+    }
+
+    HRESULT hr = device->SetVertexDeclaration(decl);
+    if (FAILED(hr)) {
+      dxgsg9_cat.error()
+        << "SetVertexDeclaration failed: " << D3DERRORSTRING(hr);
+      return false;
+    }
+
+    // Prepare and bind the vertex buffers.
+    size_t num_arrays = _data_reader->get_num_arrays();
+    size_t i;
+    for (i = 0; i < num_arrays; ++i) {
+      const GeomVertexArrayDataHandle *array_reader = _data_reader->get_array_reader(i);
+
+      // Get the vertex buffer for this array.
+      DXVertexBufferContext9 *dvbc;
+      if (!setup_array_data(dvbc, array_reader, force)) {
+        dxgsg9_cat.error() << "Unable to setup vertex buffer for array " << i << "\n";
+        _d3d_device->SetStreamSource(i, nullptr, 0, 0);
+        continue;
       }
-    } else {
-      if (!_current_shader_context->
-          update_shader_vertex_arrays(_vertex_array_shader_context, this, force)) {
-        return false;
+
+      // Bind this array as the data source for the corresponding stream.
+      const GeomVertexArrayFormat *array_format = array_reader->get_array_format();
+      hr = device->SetStreamSource(i, dvbc->_vbuffer, 0, array_format->get_stride());
+      if (FAILED(hr)) {
+        dxgsg9_cat.error() << "SetStreamSource failed" << D3DERRORSTRING(hr);
       }
     }
-  }
 
-  _vertex_array_shader = _current_shader;
-  _vertex_array_shader_context = _current_shader_context;
+    if (format->get_color_array_index() < 0 && _current_shader_context->uses_vertex_color()) {
+      // Has no vertex colors, so bind a vertex buffer containing a single
+      // white color.
+      LPDIRECT3DVERTEXBUFFER9 vbuffer = get_white_vbuffer();
+      hr = device->SetStreamSource(i, vbuffer, 0, 0);
+      if (FAILED(hr)) {
+        dxgsg9_cat.error() << "SetStreamSource failed" << D3DERRORSTRING(hr);
+      }
+      ++i;
+    }
+
+    // Unbind any other streams.
+    for (; i < _num_bound_streams; ++i) {
+      _d3d_device->SetStreamSource(i, nullptr, 0, 0);
+    }
+
+    _num_bound_streams = num_arrays;
+  }
 
   return true;
 }
@@ -1309,24 +1325,24 @@ update_standard_vertex_arrays(bool force) {
   int fvf = 0;
   HRESULT hr;
 
-  int number_of_arrays = _data_reader->get_num_arrays();
-  for ( int array_index = 0; array_index < number_of_arrays; ++array_index ) {
-    const GeomVertexArrayDataHandle* array_reader = _data_reader->get_array_reader( array_index );
-    if ( array_reader == nullptr ) {
+  int num_arrays = _data_reader->get_num_arrays();
+  for (int array_index = 0; array_index < num_arrays; ++array_index) {
+    const GeomVertexArrayDataHandle *array_reader = _data_reader->get_array_reader(array_index);
+    if (array_reader == nullptr) {
       dxgsg9_cat.error() << "Unable to get reader for array " << array_index << "\n";
       return false;
     }
 
     // Get the vertex buffer for this array.
-    DXVertexBufferContext9* dvbc;
+    DXVertexBufferContext9 *dvbc;
     if (!setup_array_data(dvbc, array_reader, force)) {
       dxgsg9_cat.error() << "Unable to setup vertex buffer for array " << array_index << "\n";
       return false;
     }
 
     // Bind this array as the data source for the corresponding stream.
-    const GeomVertexArrayFormat* array_format = array_reader->get_array_format();
-    hr = _d3d_device->SetStreamSource( array_index, dvbc->_vbuffer, 0, array_format->get_stride() );
+    const GeomVertexArrayFormat *array_format = array_reader->get_array_format();
+    hr = _d3d_device->SetStreamSource(array_index, dvbc->_vbuffer, 0, array_format->get_stride());
     if (FAILED(hr)) {
       dxgsg9_cat.error() << "SetStreamSource failed" << D3DERRORSTRING(hr);
       return false;
@@ -1336,7 +1352,13 @@ update_standard_vertex_arrays(bool force) {
     fvf |= dvbc->_fvf;
   }
 
-  hr = _d3d_device->SetFVF( fvf );
+  for (int array_index = num_arrays; array_index < _num_bound_streams; ++array_index) {
+    _d3d_device->SetStreamSource(array_index, nullptr, 0, 0);
+  }
+
+  _num_bound_streams = num_arrays;
+
+  hr = _d3d_device->SetFVF(fvf);
   if (FAILED(hr)) {
     dxgsg9_cat.error() << "SetFVF failed" << D3DERRORSTRING(hr);
     return false;
@@ -1353,9 +1375,8 @@ update_standard_vertex_arrays(bool force) {
  */
 void DXGraphicsStateGuardian9::
 disable_standard_vertex_arrays() {
-  for ( int array_index = 0; array_index < _num_bound_streams; ++array_index )
-  {
-    _d3d_device->SetStreamSource( array_index, nullptr, 0, 0 );
+  for (int array_index = 0; array_index < _num_bound_streams; ++array_index) {
+    _d3d_device->SetStreamSource(array_index, nullptr, 0, 0);
   }
   _num_bound_streams = 0;
 }
@@ -2274,6 +2295,7 @@ reset() {
   _pixel_shader_version_minor = D3DSHADER_VERSION_MINOR (d3d_caps.PixelShaderVersion);
 
   _supports_hlsl = (_pixel_shader_version_major != 0);
+  _supports_basic_shaders = _supports_hlsl;
 
   _vertex_shader_profile = (char *) D3DXGetVertexShaderProfile (_d3d_device);
   _pixel_shader_profile = (char *) D3DXGetPixelShaderProfile (_d3d_device);
@@ -2711,8 +2733,6 @@ reset() {
 
   _current_shader = nullptr;
   _current_shader_context = nullptr;
-  _vertex_array_shader = nullptr;
-  _vertex_array_shader_context = nullptr;
   _texture_binding_shader = nullptr;
   _texture_binding_shader_context = nullptr;
 

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

@@ -291,8 +291,6 @@ protected:
 
   PT(Shader) _current_shader;
   DXShaderContext9 *_current_shader_context;
-  PT(Shader) _vertex_array_shader;
-  DXShaderContext9 *_vertex_array_shader_context;
   PT(Shader) _texture_binding_shader;
   DXShaderContext9 *_texture_binding_shader_context;
 

+ 9 - 5
panda/src/dxgsg9/dxShaderContext9.I

@@ -11,6 +11,14 @@
  * @date 2006-01
  */
 
+/**
+ * Returns true if the shader needs vertex colors.
+ */
+INLINE bool DXShaderContext9::
+uses_vertex_color() {
+  return _uses_vertex_color;
+}
+
 /**
  * Returns true if the shader is "valid", ie, if the compilation was
  * successful.  The compilation could fail if there is a syntax error in the
@@ -19,9 +27,5 @@
  */
 INLINE bool DXShaderContext9::
 valid(GSG *gsg) {
-#ifdef HAVE_CG
-  return (_cg_program != 0);
-#else
-  return false;
-#endif
+  return _vertex_shader != nullptr && _pixel_shader != nullptr;
 }

File diff suppressed because it is too large
+ 736 - 490
panda/src/dxgsg9/dxShaderContext9.cxx


+ 21 - 13
panda/src/dxgsg9/dxShaderContext9.h

@@ -62,31 +62,39 @@ public:
   DXShaderContext9(Shader *s, GSG *gsg);
   ~DXShaderContext9();
 
+  bool compile_module(const ShaderModule *module, DWORD *&data);
+  bool query_constants(const ShaderModule *module, DWORD *data);
+
+  INLINE bool uses_vertex_color();
+
   INLINE bool valid(GSG *gsg);
   bool bind(GSG *gsg);
   void unbind(GSG *gsg);
   void issue_parameters(GSG *gsg, int altered);
   void issue_transform(GSG *gsg);
-  void disable_shader_vertex_arrays(GSG *gsg);
-  bool update_shader_vertex_arrays(DXShaderContext9 *prev, GSG *gsg,
-                                   bool force);
   void disable_shader_texture_bindings(GSG *gsg);
   void update_shader_texture_bindings(DXShaderContext9 *prev, GSG *gsg);
 
-  class VertexElementArray* _vertex_element_array;
-  LPDIRECT3DVERTEXDECLARATION9 _vertex_declaration;
+  LPDIRECT3DVERTEXDECLARATION9 get_vertex_declaration(GSG *gsg, const GeomVertexFormat *format);
+
+private:
+  IDirect3DVertexShader9 *_vertex_shader = nullptr;
+  IDirect3DPixelShader9 *_pixel_shader = nullptr;
 
-  int _num_bound_streams;
+  struct ConstantRegister {
+    int vreg = -1;
+    int freg = -1;
+    D3DXREGISTER_SET set;
+    UINT count = 0;
+  };
 
-  // FOR DEBUGGING
-  std::string _name;
+  bool _uses_vertex_color = false;
+  int _half_pixel_register = -1;
+  pvector<ConstantRegister> _register_map;
 
-private:
-#ifdef HAVE_CG
-  CGprogram _cg_program;
-  pvector <CGparameter> _cg_parameter_map;
-#endif
+  pmap<CPT(GeomVertexFormat), LPDIRECT3DVERTEXDECLARATION9> _vertex_declarations;
 
+  int _frame_number = -1;
   LMatrix4 *_mat_part_cache = nullptr;
 
 private:

Some files were not shown because too many files changed in this diff