|
|
@@ -18,6 +18,7 @@
|
|
|
#include "preparedGraphicsObjects.h"
|
|
|
#include "virtualFileSystem.h"
|
|
|
#include "config_util.h"
|
|
|
+#include "bamCache.h"
|
|
|
|
|
|
#ifdef HAVE_CG
|
|
|
#include <Cg/cg.h>
|
|
|
@@ -28,7 +29,6 @@ Shader::ShaderTable Shader::_load_table;
|
|
|
Shader::ShaderTable Shader::_make_table;
|
|
|
Shader::ShaderCaps Shader::_default_caps;
|
|
|
int Shader::_shaders_generated;
|
|
|
-ShaderUtilization Shader::_shader_utilization = SUT_unspecified;
|
|
|
|
|
|
#ifdef HAVE_CG
|
|
|
CGcontext Shader::_cg_context = 0;
|
|
|
@@ -1460,7 +1460,6 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: Shader::clear_parameters
|
|
|
// Access: Private
|
|
|
@@ -1473,6 +1472,38 @@ clear_parameters() {
|
|
|
_tex_spec.clear();
|
|
|
}
|
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Shader::set_compiled
|
|
|
+// Access: Private
|
|
|
+// Description: Called by the back-end when the shader has compiled
|
|
|
+// data available.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void Shader::
|
|
|
+set_compiled(unsigned int format, const char *data, size_t length) {
|
|
|
+ _compiled_format = format;
|
|
|
+ _compiled_binary.assign(data, length);
|
|
|
+
|
|
|
+ // Store the compiled shader in the cache.
|
|
|
+ if (_cache_compiled_shader && !_record.is_null()) {
|
|
|
+ _record->set_data(this);
|
|
|
+
|
|
|
+ BamCache *cache = BamCache::get_global_ptr();
|
|
|
+ cache->store(_record);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Shader::get_compiled
|
|
|
+// Access: Private
|
|
|
+// Description: Called by the back-end to retrieve compiled data.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+bool Shader::
|
|
|
+get_compiled(unsigned int &format, string &binary) const {
|
|
|
+ format = _compiled_format;
|
|
|
+ binary = _compiled_binary;
|
|
|
+ return !binary.empty();
|
|
|
+}
|
|
|
+
|
|
|
#ifdef HAVE_CG
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: Shader::cg_parameter_type
|
|
|
@@ -2204,7 +2235,8 @@ Shader(ShaderLanguage lang) :
|
|
|
_loaded(false),
|
|
|
_language(lang),
|
|
|
_last_modified(0),
|
|
|
- _mat_deps(0)
|
|
|
+ _mat_deps(0),
|
|
|
+ _cache_compiled_shader(false)
|
|
|
{
|
|
|
#ifdef HAVE_CG
|
|
|
_cg_vprogram = 0;
|
|
|
@@ -2234,7 +2266,7 @@ Shader(ShaderLanguage lang) :
|
|
|
// Returns a boolean indicating success or failure.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
bool Shader::
|
|
|
-read(const ShaderFile &sfile) {
|
|
|
+read(const ShaderFile &sfile, BamCacheRecord *record) {
|
|
|
_text._separate = sfile._separate;
|
|
|
|
|
|
if (sfile._separate) {
|
|
|
@@ -2244,30 +2276,37 @@ read(const ShaderFile &sfile) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- if (!sfile._vertex.empty() && !do_read_source(_text._vertex, sfile._vertex)) {
|
|
|
+ if (!sfile._vertex.empty() &&
|
|
|
+ !do_read_source(_text._vertex, sfile._vertex, record)) {
|
|
|
return false;
|
|
|
}
|
|
|
- if (!sfile._fragment.empty() && !do_read_source(_text._fragment, sfile._fragment)) {
|
|
|
+ if (!sfile._fragment.empty() &&
|
|
|
+ !do_read_source(_text._fragment, sfile._fragment, record)) {
|
|
|
return false;
|
|
|
}
|
|
|
- if (!sfile._geometry.empty() && !do_read_source(_text._geometry, sfile._geometry)) {
|
|
|
+ if (!sfile._geometry.empty() &&
|
|
|
+ !do_read_source(_text._geometry, sfile._geometry, record)) {
|
|
|
return false;
|
|
|
}
|
|
|
- if (!sfile._tess_control.empty() && !do_read_source(_text._tess_control, sfile._tess_control)) {
|
|
|
+ if (!sfile._tess_control.empty() &&
|
|
|
+ !do_read_source(_text._tess_control, sfile._tess_control, record)) {
|
|
|
return false;
|
|
|
}
|
|
|
- if (!sfile._tess_evaluation.empty() && !do_read_source(_text._tess_evaluation, sfile._tess_evaluation)) {
|
|
|
+ if (!sfile._tess_evaluation.empty() &&
|
|
|
+ !do_read_source(_text._tess_evaluation, sfile._tess_evaluation, record)) {
|
|
|
return false;
|
|
|
}
|
|
|
- if (!sfile._compute.empty() && !do_read_source(_text._compute, sfile._compute)) {
|
|
|
+ if (!sfile._compute.empty() &&
|
|
|
+ !do_read_source(_text._compute, sfile._compute, record)) {
|
|
|
return false;
|
|
|
}
|
|
|
_filename = sfile;
|
|
|
|
|
|
} else {
|
|
|
- if (!do_read_source(_text._shared, sfile._shared)) {
|
|
|
+ if (!do_read_source(_text._shared, sfile._shared, record)) {
|
|
|
return false;
|
|
|
}
|
|
|
+ _fullpath = _source_files[0];
|
|
|
_filename = sfile;
|
|
|
|
|
|
// Determine which language the shader is written in.
|
|
|
@@ -2323,12 +2362,12 @@ read(const ShaderFile &sfile) {
|
|
|
// bad enough to consider it 'invalid'.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
bool Shader::
|
|
|
-do_read_source(string &into, const Filename &fn) {
|
|
|
+do_read_source(string &into, const Filename &fn, BamCacheRecord *record) {
|
|
|
if (_language == SL_GLSL && glsl_preprocess) {
|
|
|
// Preprocess the GLSL file as we read it.
|
|
|
set<Filename> open_files;
|
|
|
ostringstream sstr;
|
|
|
- if (!r_preprocess_source(sstr, fn, Filename(), open_files)) {
|
|
|
+ if (!r_preprocess_source(sstr, fn, Filename(), open_files, record)) {
|
|
|
return false;
|
|
|
}
|
|
|
into = sstr.str();
|
|
|
@@ -2350,6 +2389,9 @@ do_read_source(string &into, const Filename &fn) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ if (record != (BamCacheRecord *)NULL) {
|
|
|
+ record->add_dependent_file(vf);
|
|
|
+ }
|
|
|
_last_modified = max(_last_modified, vf->get_timestamp());
|
|
|
_source_files.push_back(vf->get_filename());
|
|
|
}
|
|
|
@@ -2368,7 +2410,8 @@ do_read_source(string &into, const Filename &fn) {
|
|
|
bool Shader::
|
|
|
r_preprocess_source(ostream &out, const Filename &fn,
|
|
|
const Filename &source_dir,
|
|
|
- set<Filename> &once_files, int depth) {
|
|
|
+ set<Filename> &once_files,
|
|
|
+ BamCacheRecord *record, int depth) {
|
|
|
|
|
|
if (depth > glsl_include_recursion_limit) {
|
|
|
shader_cat.error()
|
|
|
@@ -2402,6 +2445,9 @@ r_preprocess_source(ostream &out, const Filename &fn,
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ if (record != (BamCacheRecord *)NULL) {
|
|
|
+ record->add_dependent_file(vf);
|
|
|
+ }
|
|
|
_last_modified = max(_last_modified, vf->get_timestamp());
|
|
|
_source_files.push_back(full_fn);
|
|
|
|
|
|
@@ -2483,7 +2529,7 @@ r_preprocess_source(ostream &out, const Filename &fn,
|
|
|
}
|
|
|
|
|
|
// OK, great. Process the include.
|
|
|
- if (!r_preprocess_source(out, incfn, source_dir, once_files, depth + 1)) {
|
|
|
+ if (!r_preprocess_source(out, incfn, source_dir, once_files, record, depth + 1)) {
|
|
|
// An error occurred. Pass on the failure.
|
|
|
shader_cat.error(false) << "included at line "
|
|
|
<< lineno << " of file " << fn << ":\n " << line << "\n";
|
|
|
@@ -2768,6 +2814,14 @@ load_compute(ShaderLanguage lang, const Filename &fn) {
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
+ Filename fullpath(fn);
|
|
|
+ VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
|
|
+ if (!vfs->resolve_filename(fullpath, get_model_path())) {
|
|
|
+ shader_cat.error()
|
|
|
+ << "Could not find compute shader file: " << fn << "\n";
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
ShaderFile sfile;
|
|
|
sfile._separate = true;
|
|
|
sfile._compute = fn;
|
|
|
@@ -2785,11 +2839,29 @@ load_compute(ShaderLanguage lang, const Filename &fn) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ BamCache *cache = BamCache::get_global_ptr();
|
|
|
+ PT(BamCacheRecord) record = cache->lookup(fullpath, "sho");
|
|
|
+ if (record != (BamCacheRecord *)NULL) {
|
|
|
+ if (record->has_data()) {
|
|
|
+ shader_cat.info()
|
|
|
+ << "Compute shader " << fn << " was found in disk cache.\n";
|
|
|
+
|
|
|
+ return DCAST(Shader, record->get_data());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
PT(Shader) shader = new Shader(lang);
|
|
|
- if (!shader->read(sfile)) {
|
|
|
+
|
|
|
+ if (!shader->read(sfile, record)) {
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
+ // It makes little sense to cache the shader before compilation, so
|
|
|
+ // we keep the record for when we have the compiled the shader.
|
|
|
+ swap(shader->_record, record);
|
|
|
+ shader->_cache_compiled_shader = BamCache::get_global_ptr()->get_cache_compiled_shaders();
|
|
|
+ shader->_fullpath = shader->_source_files[0];
|
|
|
+
|
|
|
_load_table[sfile] = shader;
|
|
|
return shader;
|
|
|
}
|
|
|
@@ -3195,11 +3267,9 @@ clear() {
|
|
|
_active_vprofile = CG_PROFILE_UNKNOWN;
|
|
|
_active_fprofile = CG_PROFILE_UNKNOWN;
|
|
|
_active_gprofile = CG_PROFILE_UNKNOWN;
|
|
|
- _active_fprofile = CG_PROFILE_UNKNOWN;
|
|
|
_ultimate_vprofile = CG_PROFILE_UNKNOWN;
|
|
|
_ultimate_fprofile = CG_PROFILE_UNKNOWN;
|
|
|
_ultimate_gprofile = CG_PROFILE_UNKNOWN;
|
|
|
- _ultimate_fprofile = CG_PROFILE_UNKNOWN;
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
@@ -3211,7 +3281,7 @@ clear() {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void Shader::
|
|
|
register_with_read_factory() {
|
|
|
- //BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
|
|
+ BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -3226,6 +3296,9 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
|
|
dg.add_bool(_loaded);
|
|
|
_filename.write_datagram(dg);
|
|
|
_text.write_datagram(dg);
|
|
|
+
|
|
|
+ dg.add_uint32(_compiled_format);
|
|
|
+ dg.add_string(_compiled_binary);
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -3260,4 +3333,7 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|
|
_loaded = scan.get_bool();
|
|
|
_filename.read_datagram(scan);
|
|
|
_text.read_datagram(scan);
|
|
|
+
|
|
|
+ _compiled_format = scan.get_uint32();
|
|
|
+ _compiled_binary = scan.get_string();
|
|
|
}
|