glsl: make ParamVecBase4 and ParamVecBase4i work with ptr inputs

This commit is contained in:
rdb 2019-04-14 23:08:02 +02:00
parent 66ea0471a0
commit 6df700939a
6 changed files with 111 additions and 20 deletions

View File

@ -1901,6 +1901,14 @@ fetch_ptr_parameter(const Shader::ShaderPtrSpec& spec) {
return (_target_shader->get_shader_input_ptr(spec._arg)); 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 * Makes the specified DisplayRegion current. All future drawing and clear
* operations will be constrained within the given DisplayRegion. * operations will be constrained within the given DisplayRegion.

View File

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

View File

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

View File

@ -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 * Returns the ShaderInput as a texture. Assertion fails if there is none, or
* if it is not a texture. * if it is not a texture.

View File

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

View File

@ -294,6 +294,36 @@ def test_glsl_pta_mat4(gsg):
run_glsl_test(gsg, code, preamble, {'pta': pta}) 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): def test_glsl_write_extract_image_buffer(gsg):
# Tests that we can write to a buffer texture on the GPU, and then extract # 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 # the data on the CPU. We test two textures since there was in the past a