Bug 1510490 - Add versioning support for serialized shaders. r=mattwoodrow
☠☠ backed out by b425a0d640af ☠ ☠
authorBobby Holley <bobbyholley@gmail.com>
Sat, 01 Dec 2018 03:06:08 +0000
changeset 508290 55fa8c9b0c7e895c476d26452debc13a8b4678c1
parent 508289 ee215fdef53fbccacf05ef299e2b3367100645bf
child 508291 f9d8e4ebe0a2f40646dff560a0cdccd0f722f3ea
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1510490
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1510490 - Add versioning support for serialized shaders. r=mattwoodrow Depends on D13442 Differential Revision: https://phabricator.services.mozilla.com/D13443
gfx/webrender_bindings/src/program_cache.rs
--- a/gfx/webrender_bindings/src/program_cache.rs
+++ b/gfx/webrender_bindings/src/program_cache.rs
@@ -16,27 +16,34 @@ use uuid::Uuid;
 const MAX_LOAD_TIME_MS: u64 = 400;
 const MAX_CACHED_PROGRAM_COUNT: u32 = 15;
 
 fn deserialize_program_binary(path: &PathBuf) -> Result<Arc<ProgramBinary>, Error> {
     let mut buf = vec![];
     let mut file = File::open(path)?;
     file.read_to_end(&mut buf)?;
 
-    if buf.len() <= 8 {
+    if buf.len() <= 8 + 4 {
         return Err(Error::new(ErrorKind::InvalidData, "File size is too small"));
     }
-    let hash = &buf[0 .. 8];
-    let data = &buf[8 ..];
+    let magic = &buf[0 .. 4];
+    let hash = &buf[4 .. 8 + 4];
+    let data = &buf[8 + 4 ..];
+
+    // Check if magic + version are correct.
+    let mv:u32 = bincode::deserialize(&magic).unwrap();
+    if mv != MAGIC_AND_VERSION {
+        return Err(Error::new(ErrorKind::InvalidData, "File data is invalid (magic+version)"));
+    }
 
     // Check if hash is correct
     let hash:u64 = bincode::deserialize(&hash).unwrap();
     let hash_data = fxhash::hash64(&data);
     if hash != hash_data {
-        return Err(Error::new(ErrorKind::InvalidData, "File data is invalid"));
+        return Err(Error::new(ErrorKind::InvalidData, "File data is invalid (hash)"));
     }
 
     // Deserialize ProgramBinary
     let binary = match bincode::deserialize(&data) {
         Ok(binary) => binary,
         Err(_) => return Err(Error::new(ErrorKind::InvalidData, "Failed to deserialize ProgramBinary")),
     };
 
@@ -79,16 +86,21 @@ fn get_cache_path_from_prof_path(prof_pa
 
 struct WrProgramBinaryDiskCache {
     cache_path: Option<PathBuf>,
     program_count: u32,
     is_enabled: bool,
     workers: Arc<ThreadPool>,
 }
 
+// Magic number + version. Increment the version when the binary format changes.
+const MAGIC: u32 = 0xB154AD30; // BI-SHADE + version.
+const VERSION: u32 = 2;
+const MAGIC_AND_VERSION: u32 = MAGIC + VERSION;
+
 impl WrProgramBinaryDiskCache {
     #[allow(dead_code)]
     fn new(prof_path: &nsAString, workers: &Arc<ThreadPool>) -> Self {
         let cache_path = get_cache_path_from_prof_path(prof_path);
         let is_enabled = cache_path.is_some();
         let workers = Arc::clone(workers);
 
         WrProgramBinaryDiskCache{
@@ -142,16 +154,27 @@ impl WrProgramBinaryDiskCache {
                 let mut file = match File::create(&file_path) {
                     Ok(file) => file,
                     Err(err) => {
                         error!("Unable to create file for program binary error: {}", err);
                         return;
                     }
                 };
 
+                // Write magic + version.
+                let mv = MAGIC_AND_VERSION;
+                let mv = bincode::serialize(&mv).unwrap();
+                assert!(mv.len() == 4);
+                match file.write_all(&mv) {
+                    Err(err) => {
+                        error!("Failed to write magic+version to file error: {}", err);
+                    }
+                    _ => {},
+                };
+
                 // Write hash
                 let hash = fxhash::hash64(&data);
                 let hash = bincode::serialize(&hash).unwrap();
                 assert!(hash.len() == 8);
                 match file.write_all(&hash) {
                     Err(err) => {
                         error!("Failed to write hash to file error: {}", err);
                     }