Browse Source

glsl: make ParamVecBase4 and ParamVecBase4i work with ptr inputs

rdb 6 years ago
parent
commit
6df700939a

+ 8 - 0
panda/src/display/graphicsStateGuardian.cxx

@@ -1901,6 +1901,14 @@ fetch_ptr_parameter(const Shader::ShaderPtrSpec& spec) {
   return (_target_shader->get_shader_input_ptr(spec._arg));
 }
 
+/**
+ *
+ */
+bool GraphicsStateGuardian::
+fetch_ptr_parameter(const Shader::ShaderPtrSpec& spec, Shader::ShaderPtrData &data) {
+  return _target_shader->get_shader_input_ptr(spec._arg, data);
+}
+
 /**
  * Makes the specified DisplayRegion current.  All future drawing and clear
  * operations will be constrained within the given DisplayRegion.

+ 1 - 0
panda/src/display/graphicsStateGuardian.h

@@ -339,6 +339,7 @@ public:
   PT(Texture) fetch_specified_texture(Shader::ShaderTexSpec &spec,
                                       SamplerState &sampler, int &view);
   const Shader::ShaderPtrData *fetch_ptr_parameter(const Shader::ShaderPtrSpec& spec);
+  bool fetch_ptr_parameter(const Shader::ShaderPtrSpec &spec, Shader::ShaderPtrData &data);
 
   virtual void prepare_display_region(DisplayRegionPipelineReader *dr);
   virtual void clear_before_callback();

+ 20 - 20
panda/src/glstuff/glShaderContext_src.cxx

@@ -2110,8 +2110,8 @@ issue_parameters(int altered) {
     for (int i = 0; i < (int)_shader->_ptr_spec.size(); ++i) {
       Shader::ShaderPtrSpec &spec = _shader->_ptr_spec[i];
 
-      const Shader::ShaderPtrData* ptr_data = _glgsg->fetch_ptr_parameter(spec);
-      if (ptr_data == nullptr) { //the input is not contained in ShaderPtrData
+      Shader::ShaderPtrData ptr_data;
+      if (!_glgsg->fetch_ptr_parameter(spec, ptr_data)) { //the input is not contained in ShaderPtrData
         release_resources();
         return;
       }
@@ -2119,18 +2119,18 @@ issue_parameters(int altered) {
       nassertd(spec._dim[1] > 0) continue;
 
       GLint p = spec._id._seqno;
-      int array_size = min(spec._dim[0], (int)ptr_data->_size / spec._dim[1]);
+      int array_size = min(spec._dim[0], (int)ptr_data._size / spec._dim[1]);
       switch (spec._type) {
       case Shader::SPT_float:
         {
           float *data = nullptr;
 
-          switch (ptr_data->_type) {
+          switch (ptr_data._type) {
           case Shader::SPT_int:
             // Convert int data to float data.
             data = (float*) alloca(sizeof(float) * array_size * spec._dim[1]);
             for (int i = 0; i < (array_size * spec._dim[1]); ++i) {
-              data[i] = (float)(((int*)ptr_data->_ptr)[i]);
+              data[i] = (float)(((int*)ptr_data._ptr)[i]);
             }
             break;
 
@@ -2138,7 +2138,7 @@ issue_parameters(int altered) {
             // Convert unsigned int data to float data.
             data = (float*) alloca(sizeof(float) * array_size * spec._dim[1]);
             for (int i = 0; i < (array_size * spec._dim[1]); ++i) {
-              data[i] = (float)(((unsigned int*)ptr_data->_ptr)[i]);
+              data[i] = (float)(((unsigned int*)ptr_data._ptr)[i]);
             }
             break;
 
@@ -2146,12 +2146,12 @@ issue_parameters(int altered) {
             // Downgrade double data to float data.
             data = (float*) alloca(sizeof(float) * array_size * spec._dim[1]);
             for (int i = 0; i < (array_size * spec._dim[1]); ++i) {
-              data[i] = (float)(((double*)ptr_data->_ptr)[i]);
+              data[i] = (float)(((double*)ptr_data._ptr)[i]);
             }
             break;
 
           case Shader::SPT_float:
-            data = (float*)ptr_data->_ptr;
+            data = (float*)ptr_data._ptr;
             break;
 
           default:
@@ -2171,8 +2171,8 @@ issue_parameters(int altered) {
         break;
 
       case Shader::SPT_int:
-        if (ptr_data->_type != Shader::SPT_int &&
-            ptr_data->_type != Shader::SPT_uint) {
+        if (ptr_data._type != Shader::SPT_int &&
+            ptr_data._type != Shader::SPT_uint) {
           GLCAT.error()
             << "Cannot pass floating-point data to integer shader input '" << spec._id._name << "'\n";
 
@@ -2183,18 +2183,18 @@ issue_parameters(int altered) {
 
         } else {
           switch (spec._dim[1]) {
-          case 1: _glgsg->_glUniform1iv(p, array_size, (int*)ptr_data->_ptr); continue;
-          case 2: _glgsg->_glUniform2iv(p, array_size, (int*)ptr_data->_ptr); continue;
-          case 3: _glgsg->_glUniform3iv(p, array_size, (int*)ptr_data->_ptr); continue;
-          case 4: _glgsg->_glUniform4iv(p, array_size, (int*)ptr_data->_ptr); continue;
+          case 1: _glgsg->_glUniform1iv(p, array_size, (int*)ptr_data._ptr); continue;
+          case 2: _glgsg->_glUniform2iv(p, array_size, (int*)ptr_data._ptr); continue;
+          case 3: _glgsg->_glUniform3iv(p, array_size, (int*)ptr_data._ptr); continue;
+          case 4: _glgsg->_glUniform4iv(p, array_size, (int*)ptr_data._ptr); continue;
           }
           nassertd(false) continue;
         }
         break;
 
       case Shader::SPT_uint:
-        if (ptr_data->_type != Shader::SPT_uint &&
-            ptr_data->_type != Shader::SPT_int) {
+        if (ptr_data._type != Shader::SPT_uint &&
+            ptr_data._type != Shader::SPT_int) {
           GLCAT.error()
             << "Cannot pass floating-point data to integer shader input '" << spec._id._name << "'\n";
 
@@ -2205,10 +2205,10 @@ issue_parameters(int altered) {
 
         } else {
           switch (spec._dim[1]) {
-          case 1: _glgsg->_glUniform1uiv(p, array_size, (GLuint *)ptr_data->_ptr); continue;
-          case 2: _glgsg->_glUniform2uiv(p, array_size, (GLuint *)ptr_data->_ptr); continue;
-          case 3: _glgsg->_glUniform3uiv(p, array_size, (GLuint *)ptr_data->_ptr); continue;
-          case 4: _glgsg->_glUniform4uiv(p, array_size, (GLuint *)ptr_data->_ptr); continue;
+          case 1: _glgsg->_glUniform1uiv(p, array_size, (GLuint *)ptr_data._ptr); continue;
+          case 2: _glgsg->_glUniform2uiv(p, array_size, (GLuint *)ptr_data._ptr); continue;
+          case 3: _glgsg->_glUniform3uiv(p, array_size, (GLuint *)ptr_data._ptr); continue;
+          case 4: _glgsg->_glUniform4uiv(p, array_size, (GLuint *)ptr_data._ptr); continue;
           }
           nassertd(false) continue;
         }

+ 51 - 0
panda/src/pgraph/shaderAttrib.cxx

@@ -422,6 +422,57 @@ get_shader_input_ptr(const InternalName *id) const {
   }
 }
 
+/**
+ * Returns the ShaderInput as a ShaderPtrData struct.  Assertion fails if
+ * there is none.  or if it is not a PTA(double/float)
+ */
+bool ShaderAttrib::
+get_shader_input_ptr(const InternalName *id, Shader::ShaderPtrData &data) const {
+  Inputs::const_iterator i = _inputs.find(id);
+  if (i != _inputs.end()) {
+    const ShaderInput &p = (*i).second;
+    if (p.get_value_type() == ShaderInput::M_numeric ||
+        p.get_value_type() == ShaderInput::M_vector) {
+
+      data = p.get_ptr();
+      return (data._ptr != nullptr);
+    }
+    if (p.get_value_type() == ShaderInput::M_param) {
+      // Temporary solution until the new param system
+      TypedWritableReferenceCount *param = p.get_value();
+      if (param != nullptr) {
+        if (param->is_of_type(ParamVecBase4f::get_class_type())) {
+          data._ptr = (void *)((const ParamVecBase4f *)param)->get_value().get_data();
+          data._size = 4;
+          data._type = Shader::SPT_float;
+          return true;
+        }
+        else if (param->is_of_type(ParamVecBase4i::get_class_type())) {
+          data._ptr = (void *)((const ParamVecBase4i *)param)->get_value().get_data();
+          data._size = 4;
+          data._type = Shader::SPT_int;
+          return true;
+        }
+        else if (param->is_of_type(ParamVecBase4d::get_class_type())) {
+          data._ptr = (void *)((const ParamVecBase4d *)param)->get_value().get_data();
+          data._size = 4;
+          data._type = Shader::SPT_float;
+          return true;
+        }
+      }
+    }
+    ostringstream strm;
+    strm << "Shader input " << id->get_name() << " was given an incompatible parameter type.\n";
+    nassert_raise(strm.str());
+    return false;
+  } else {
+    ostringstream strm;
+    strm << "Shader input " << id->get_name() << " is not present.\n";
+    nassert_raise(strm.str());
+    return false;
+  }
+}
+
 /**
  * Returns the ShaderInput as a texture.  Assertion fails if there is none, or
  * if it is not a texture.

+ 1 - 0
panda/src/pgraph/shaderAttrib.h

@@ -119,6 +119,7 @@ PUBLISHED:
   LVecBase4 get_shader_input_vector(InternalName *id) const;
   Texture *get_shader_input_texture(const InternalName *id, SamplerState *sampler=nullptr) const;
   const Shader::ShaderPtrData *get_shader_input_ptr(const InternalName *id) const;
+  bool get_shader_input_ptr(const InternalName *id, Shader::ShaderPtrData &data) const;
   const LMatrix4 &get_shader_input_matrix(const InternalName *id, LMatrix4 &matrix) const;
   ShaderBuffer *get_shader_input_buffer(const InternalName *id) const;
 

+ 30 - 0
tests/display/test_glsl_shader.py

@@ -294,6 +294,36 @@ def test_glsl_pta_mat4(gsg):
     run_glsl_test(gsg, code, preamble, {'pta': pta})
 
 
+def test_glsl_param_vec4(gsg):
+    param = core.ParamVecBase4((0, 1, 2, 3))
+
+    preamble = """
+    uniform vec4 param;
+    """
+    code = """
+    assert(param.x == 0.0);
+    assert(param.y == 1.0);
+    assert(param.z == 2.0);
+    assert(param.w == 3.0);
+    """
+    run_glsl_test(gsg, code, preamble, {'param': param})
+
+
+def test_glsl_param_ivec4(gsg):
+    param = core.ParamVecBase4i((0, 1, 2, 3))
+
+    preamble = """
+    uniform ivec4 param;
+    """
+    code = """
+    assert(param.x == 0);
+    assert(param.y == 1);
+    assert(param.z == 2);
+    assert(param.w == 3);
+    """
+    run_glsl_test(gsg, code, preamble, {'param': param})
+
+
 def test_glsl_write_extract_image_buffer(gsg):
     # Tests that we can write to a buffer texture on the GPU, and then extract
     # the data on the CPU.  We test two textures since there was in the past a