From 6df700939a5c5af728dea2479df70be644ebe1c9 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 14 Apr 2019 23:08:02 +0200 Subject: [PATCH] glsl: make ParamVecBase4 and ParamVecBase4i work with ptr inputs --- panda/src/display/graphicsStateGuardian.cxx | 8 ++++ panda/src/display/graphicsStateGuardian.h | 1 + panda/src/glstuff/glShaderContext_src.cxx | 40 ++++++++-------- panda/src/pgraph/shaderAttrib.cxx | 51 +++++++++++++++++++++ panda/src/pgraph/shaderAttrib.h | 1 + tests/display/test_glsl_shader.py | 30 ++++++++++++ 6 files changed, 111 insertions(+), 20 deletions(-) diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 749fbc7b35..851ca112ea 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/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. diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index e1c9435fef..cb556499b2 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/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(); diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 5a7eda65fc..8789f26650 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/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; } diff --git a/panda/src/pgraph/shaderAttrib.cxx b/panda/src/pgraph/shaderAttrib.cxx index 24b245b218..934773ad49 100644 --- a/panda/src/pgraph/shaderAttrib.cxx +++ b/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. diff --git a/panda/src/pgraph/shaderAttrib.h b/panda/src/pgraph/shaderAttrib.h index 29b535ff8a..fb0cc6e996 100644 --- a/panda/src/pgraph/shaderAttrib.h +++ b/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; diff --git a/tests/display/test_glsl_shader.py b/tests/display/test_glsl_shader.py index 8deadf40d9..401166a26d 100644 --- a/tests/display/test_glsl_shader.py +++ b/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