]> git.sesse.net Git - movit/commitdiff
Compile shaders into the library.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Wed, 22 Feb 2023 22:35:50 +0000 (23:35 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Wed, 22 Feb 2023 22:38:30 +0000 (23:38 +0100)
This was long overdue; I was reluctant for a while since it's easier
to develop or debug shaders this way, but the solution is of course
to give priority to the filesystem.

It is now allowed to give "" as the data directory, which will only
ever look in the bundle. Most users should probably just do that.

Shaders are no longer installed by make install.

There is no API or ABI break, but of course, you cannot give ""
as directory to older versions (it would mean essentially /).

.gitignore
Makefile.in
bundled_shaders.h [new file with mode: 0644]
init.h
make_bundled_shaders.cpp [new file with mode: 0644]
util.cpp
version.h

index e9f545ed46b235b1ef8f1cb7174becd9e764b294..a918e0049cf1a2f428cc5672356bc8d0a019b131 100644 (file)
@@ -11,6 +11,8 @@
 perf.data
 *.dot
 demo
 perf.data
 *.dot
 demo
+make_bundled_shaders
+bundled_shaders.cpp
 effect_chain_test
 compute_shader_test
 gamma_compression_effect_test
 effect_chain_test
 compute_shader_test
 gamma_compression_effect_test
index b021ded07dfeb9581cc249d4fc12299d2abd7417..1d874e991f64bf790450a768d08f9eb96dd18301 100644 (file)
@@ -90,7 +90,7 @@ EFFECTS = $(TESTED_EFFECTS) $(UNTESTED_EFFECTS)
 # Unit tests.
 TESTS=effect_chain_test fp16_test $(TESTED_INPUTS:=_test) $(TESTED_EFFECTS:=_test)
 
 # Unit tests.
 TESTS=effect_chain_test fp16_test $(TESTED_INPUTS:=_test) $(TESTED_EFFECTS:=_test)
 
-LIB_OBJS=effect_util.o util.o effect.o effect_chain.o init.o resource_pool.o ycbcr.o $(INPUTS:=.o) $(EFFECTS:=.o)
+LIB_OBJS=effect_util.o util.o effect.o effect_chain.o init.o resource_pool.o ycbcr.o bundled_shaders.o $(INPUTS:=.o) $(EFFECTS:=.o)
 
 # Default target:
 all: libmovit.la $(TESTS)
 
 # Default target:
 all: libmovit.la $(TESTS)
@@ -135,7 +135,8 @@ DEPS=$(OBJS:.o=.d) $(OBJS:.o=.ld)
 
 clean:
        $(LIBTOOL) --mode=clean $(RM) demo $(TESTS) libmovit.la $(OBJS) $(OBJS:.o=.lo)
 
 clean:
        $(LIBTOOL) --mode=clean $(RM) demo $(TESTS) libmovit.la $(OBJS) $(OBJS:.o=.lo)
-       $(RM) $(OBJS:.o=.gcno) $(OBJS:.o=.gcda) $(DEPS) step*.dot chain*.frag
+       $(LIBTOOL) --mode=clean $(RM) $(MAKE_BUNDLE_OBJS) $(MAKE_BUNDLE_OBJS:.o=.lo) make_bundled_shaders bundled_shaders.cpp
+       $(RM) $(OBJS:.o=.gcno) $(OBJS:.o=.gcda) $(MAKE_BUNDLE_OBJS:.o=.gcno) $(MAKE_BUNDLE_OBJS:.o=.gcda) $(DEPS) step*.dot chain*.frag
        $(RM) -r movit.info coverage/ .libs/
 
 distclean: clean
        $(RM) -r movit.info coverage/ .libs/
 
 distclean: clean
@@ -180,6 +181,13 @@ MISSING_SHADERS = diffusion_effect.frag glow_effect.frag unsharp_mask_effect.fra
 MISSING_SHADERS += fft_convolution_effect.frag fft_input.frag
 SHADERS := $(filter-out $(MISSING_SHADERS),$(SHADERS))
 
 MISSING_SHADERS += fft_convolution_effect.frag fft_input.frag
 SHADERS := $(filter-out $(MISSING_SHADERS),$(SHADERS))
 
+# A program to compile all the shaders into one bundle that we can link into the library.
+MAKE_BUNDLE_OBJS=make_bundled_shaders.o util.o init.o resource_pool.o
+make_bundled_shaders: $(MAKE_BUNDLE_OBJS)
+       $(LIBTOOL) --mode=link $(CXX) $(LDFLAGS) -o make_bundled_shaders $(MAKE_BUNDLE_OBJS) -lepoxy 
+bundled_shaders.cpp: make_bundled_shaders $(SHADERS)
+       ./make_bundled_shaders $(SHADERS) > $@
+
 install: libmovit.la
        $(MKDIR) -p $(DESTDIR)$(libdir)/
        $(LIBTOOL) --mode=install $(INSTALL) -m 0644 libmovit.la $(DESTDIR)$(libdir)/
 install: libmovit.la
        $(MKDIR) -p $(DESTDIR)$(libdir)/
        $(LIBTOOL) --mode=install $(INSTALL) -m 0644 libmovit.la $(DESTDIR)$(libdir)/
@@ -197,7 +205,6 @@ dist:
        $(MKDIR) $(DISTDIR)
        cp $(OWN_OBJS:.o=.cpp) $(DISTDIR)/
        cp $(HDRS) $(DISTDIR)/
        $(MKDIR) $(DISTDIR)
        cp $(OWN_OBJS:.o=.cpp) $(DISTDIR)/
        cp $(HDRS) $(DISTDIR)/
-       cp $(SHADERS) $(DISTDIR)/
        cp $(OTHER_DIST_FILES) $(DISTDIR)/
        ( cd $(DISTDIR) && aclocal && libtoolize --install --copy && autoconf && $(RM) -r autom4te.cache/ )
        tar zcvvf ../$(DISTDIR).tar.gz $(DISTDIR)
        cp $(OTHER_DIST_FILES) $(DISTDIR)/
        ( cd $(DISTDIR) && aclocal && libtoolize --install --copy && autoconf && $(RM) -r autom4te.cache/ )
        tar zcvvf ../$(DISTDIR).tar.gz $(DISTDIR)
diff --git a/bundled_shaders.h b/bundled_shaders.h
new file mode 100644 (file)
index 0000000..26d6e06
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _MOVIT_BUNDLED_SHADERS_H
+#define _MOVIT_BUNDLED_SHADERS_H 1
+
+// Shader files that are compiled into the library.
+
+namespace movit {
+
+struct BundledShader {
+       const char *filename;  // nullptr for end.
+       size_t offset;  // Into shader_bundle.
+       size_t length;
+};
+extern BundledShader bundled_shaders[];
+extern const char *shader_bundle;
+
+}  // namespace movit
+
+#endif  // _MOVIT_BUNDLED_SHADERS_H
diff --git a/init.h b/init.h
index 23055227a41fde49b91aed18fcb613e80c864428..2c7638a58269154c37bb15747b70524e6f135d27 100644 (file)
--- a/init.h
+++ b/init.h
@@ -17,7 +17,9 @@ enum MovitDebugLevel {
 // succeeded.
 //
 // The first parameter gives which directory to read .frag files from.
 // succeeded.
 //
 // The first parameter gives which directory to read .frag files from.
-// This is a temporary hack until we add something more solid.
+// If you use "", or the file isn't found, a compiled-in version will
+// be used instead (if it exists). Most users should probably use ""
+// unless you need backwards compatibility with Movit 1.6.3 or older.
 //
 // The second parameter specifies whether debugging is on or off.
 // If it is on, Movit will write intermediate graphs and the final
 //
 // The second parameter specifies whether debugging is on or off.
 // If it is on, Movit will write intermediate graphs and the final
diff --git a/make_bundled_shaders.cpp b/make_bundled_shaders.cpp
new file mode 100644 (file)
index 0000000..53ce13f
--- /dev/null
@@ -0,0 +1,65 @@
+#include <stdio.h>
+#include <string>
+#include <vector>
+#include "util.h"
+#include "bundled_shaders.h"
+
+using namespace std;
+using namespace movit;
+
+namespace movit {
+
+// We need a fake (empty) list of shaders, since we reuse read_file().
+BundledShader bundled_shaders[] = {
+       { nullptr, 0, 0 }
+};
+const char *shader_bundle = "";
+extern string *movit_data_directory;
+
+}  // namespace movit
+
+int main(int argc, char **argv)
+{
+       std::vector<BundledShader> shaders;
+       std::string bundle;
+
+       movit_data_directory = new string(".");
+
+       for (int i = 1; i < argc; ++i) {
+               string contents = read_file(argv[i]);
+               shaders.push_back(BundledShader{ argv[i], /*offset=*/bundle.size(), /*length=*/contents.size() });
+               bundle += contents;
+       }
+
+       printf("// Autogenerated by make_bundled_shaders.cpp. Do not edit by hand!\n");
+       printf("#include <string>\n");
+       printf("#include \"bundled_shaders.h\"\n");
+       printf("\n");
+       printf("namespace movit {\n");
+       printf("\n");
+       printf("BundledShader bundled_shaders[] = {\n");
+       for (const BundledShader &shader : shaders) {
+               printf("\t{ \"%s\", %zu, %zu },\n", shader.filename, shader.offset, shader.length);
+       }
+       printf("\t{ nullptr, 0, 0 }\n");
+       printf("};\n");
+       printf("const char *shader_bundle = \"");
+       for (unsigned char ch : bundle) {
+               if (ch == '\n') {
+                       printf("\\n");
+               } else if (ch == '\t') {
+                       printf("\\t");
+               } else if (ch == '"') { 
+                       printf("\\\"");
+               } else if (ch == '\\') {        
+                       printf("\\\\");
+               } else if (!isprint(ch)) {
+                       printf("\\0%o", ch);
+               } else {
+                       printf("%c", ch);
+               }
+       }
+       printf("\";\n");
+       printf("\n");
+       printf("}  // namespace movit\n");
+}
index 9b018825d333e269e3e0007b0300165af563b28f..085461988ed5f40440f1f2a478f704982d7f6a9d 100644 (file)
--- a/util.cpp
+++ b/util.cpp
@@ -9,6 +9,7 @@
 #include <string>
 #include <Eigen/Core>
 
 #include <string>
 #include <Eigen/Core>
 
+#include "bundled_shaders.h"
 #include "fp16.h"
 #include "init.h"
 #include "util.h"
 #include "fp16.h"
 #include "init.h"
 #include "util.h"
@@ -84,18 +85,49 @@ void hsv2rgb_normalized(float h, float s, float v, float *r, float *g, float *b)
        }
 }
 
        }
 }
 
+string read_file_from_bundle(const string &filename)
+{
+       for (const BundledShader *shader = bundled_shaders; shader->filename != nullptr; ++shader) {
+               if (shader->filename == filename) {
+                       return string(shader_bundle + shader->offset, shader->length);
+               }
+       }
+       return "";  // Not found.
+}
+
 string read_file(const string &filename)
 {
 string read_file(const string &filename)
 {
+       string contents_from_bundle = read_file_from_bundle(filename);
+
+       // If no data directory has been given, we read only from the bundle.
+       if (*movit_data_directory == "") {
+               if (contents_from_bundle.empty()) {
+                       fprintf(stderr, "%s: Shader not compiled in, and no data directory has been given.\n", filename.c_str());
+                       exit(1);
+               } else {
+                       return contents_from_bundle;
+               }
+       }
+
+       // If we're given a data directory, we still support reading from the bundle,
+       // but a successful read from the file system takes priority.
        const string full_pathname = *movit_data_directory + "/" + filename;
 
        FILE *fp = fopen(full_pathname.c_str(), "r");
        if (fp == nullptr) {
        const string full_pathname = *movit_data_directory + "/" + filename;
 
        FILE *fp = fopen(full_pathname.c_str(), "r");
        if (fp == nullptr) {
+               if (!contents_from_bundle.empty()) {
+                       return contents_from_bundle;
+               }
                perror(full_pathname.c_str());
                exit(1);
        }
 
        int ret = fseek(fp, 0, SEEK_END);
        if (ret == -1) {
                perror(full_pathname.c_str());
                exit(1);
        }
 
        int ret = fseek(fp, 0, SEEK_END);
        if (ret == -1) {
+               if (!contents_from_bundle.empty()) {
+                       fclose(fp);
+                       return contents_from_bundle;
+               }
                perror("fseek(SEEK_END)");
                exit(1);
        }
                perror("fseek(SEEK_END)");
                exit(1);
        }
@@ -104,6 +136,10 @@ string read_file(const string &filename)
 
        ret = fseek(fp, 0, SEEK_SET);
        if (ret == -1) {
 
        ret = fseek(fp, 0, SEEK_SET);
        if (ret == -1) {
+               if (!contents_from_bundle.empty()) {
+                       fclose(fp);
+                       return contents_from_bundle;
+               }
                perror("fseek(SEEK_SET)");
                exit(1);
        }
                perror("fseek(SEEK_SET)");
                exit(1);
        }
@@ -112,10 +148,18 @@ string read_file(const string &filename)
        str.resize(size);
        ret = fread(&str[0], size, 1, fp);
        if (ret == -1) {
        str.resize(size);
        ret = fread(&str[0], size, 1, fp);
        if (ret == -1) {
+               if (!contents_from_bundle.empty()) {
+                       fclose(fp);
+                       return contents_from_bundle;
+               }
                perror("fread");
                exit(1);
        }
        if (ret == 0) {
                perror("fread");
                exit(1);
        }
        if (ret == 0) {
+               if (!contents_from_bundle.empty()) {
+                       fclose(fp);
+                       return contents_from_bundle;
+               }
                fprintf(stderr, "Short read when trying to read %d bytes from %s\n",
                        size, full_pathname.c_str());
                exit(1);
                fprintf(stderr, "Short read when trying to read %d bytes from %s\n",
                        size, full_pathname.c_str());
                exit(1);
index 9c0872827662b064e873f07bd2e969878acd086f..b85acced72944ed6b1eae189cf2e735efd926e1b 100644 (file)
--- a/version.h
+++ b/version.h
@@ -5,6 +5,6 @@
 // changes, even within git versions. There is no specific version
 // documentation outside the regular changelogs, though.
 
 // changes, even within git versions. There is no specific version
 // documentation outside the regular changelogs, though.
 
-#define MOVIT_VERSION 37
+#define MOVIT_VERSION 38
 
 #endif // !defined(_MOVIT_VERSION_H)
 
 #endif // !defined(_MOVIT_VERSION_H)