Bug 1536240 - Add debug option to wrench to output specified shader source r=kvark
☠☠ backed out by 6d98129734a8 ☠ ☠
authorConnor Brewster <cbrewster@mozilla.com>
Thu, 30 May 2019 16:18:42 +0000
changeset 476249 cb8c60790fd9a7fcd503e97b83de101daee39e77
parent 476248 9b19d5f722731a104d17693b0c79d222603f4d2d
child 476250 6d98129734a866e3b8d97b8397b88022d863a7d8
push id36090
push usernbeleuzu@mozilla.com
push dateFri, 31 May 2019 03:59:09 +0000
treeherdermozilla-central@63568b2a8178 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskvark
bugs1536240
milestone69.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 1536240 - Add debug option to wrench to output specified shader source r=kvark Differential Revision: https://phabricator.services.mozilla.com/D33088
gfx/wr/webrender/src/device/gl.rs
gfx/wr/webrender/src/renderer.rs
gfx/wr/wrench/src/args.yaml
gfx/wr/wrench/src/main.rs
gfx/wr/wrench/src/wrench.rs
--- a/gfx/wr/webrender/src/device/gl.rs
+++ b/gfx/wr/webrender/src/device/gl.rs
@@ -995,16 +995,19 @@ pub struct Device {
     /// at all, or for BGRA8 format. If it's not supported for the required
     /// format, we fall back to glTexImage*.
     texture_storage_usage: TexStorageUsage,
 
     optimal_pbo_stride: NonZeroUsize,
 
     // GL extensions
     extensions: Vec<String>,
+
+    /// Dumps the source of the shader with the given name
+    dump_shader_source: Option<String>,
 }
 
 /// Contains the parameters necessary to bind a draw target.
 #[derive(Clone, Copy)]
 pub enum DrawTarget {
     /// Use the device's default draw target, with the provided dimensions,
     /// which are used to set the viewport.
     Default {
@@ -1170,16 +1173,17 @@ impl From<DrawTarget> for ReadTarget {
 
 impl Device {
     pub fn new(
         mut gl: Rc<gl::Gl>,
         resource_override_path: Option<PathBuf>,
         upload_method: UploadMethod,
         cached_programs: Option<Rc<ProgramCache>>,
         allow_pixel_local_storage_support: bool,
+        dump_shader_source: Option<String>,
     ) -> Device {
         let mut max_texture_size = [0];
         let mut max_texture_layers = [0];
         unsafe {
             gl.get_integer_v(gl::MAX_TEXTURE_SIZE, &mut max_texture_size);
             gl.get_integer_v(gl::MAX_ARRAY_TEXTURE_LAYERS, &mut max_texture_layers);
         }
 
@@ -1352,16 +1356,17 @@ impl Device {
             max_texture_size,
             max_texture_layers,
             renderer_name,
             cached_programs,
             frame_id: GpuFrameId(0),
             extensions,
             texture_storage_usage,
             optimal_pbo_stride,
+            dump_shader_source,
         }
     }
 
     pub fn gl(&self) -> &gl::Gl {
         &*self.gl
     }
 
     pub fn rc_gl(&self) -> &Rc<gl::Gl> {
@@ -1699,16 +1704,23 @@ impl Device {
                 match Device::compile_shader(&*self.gl, &info.base_filename, gl::FRAGMENT_SHADER, &fs_source) {
                     Ok(fs_id) => fs_id,
                     Err(err) => {
                         self.gl.delete_shader(vs_id);
                         return Err(err);
                     }
                 };
 
+            // Check if shader source should be dumped
+            if Some(info.base_filename) == self.dump_shader_source.as_ref().map(String::as_ref) {
+                let path = std::path::Path::new(info.base_filename);
+                std::fs::write(path.with_extension("vert"), vs_source).unwrap();
+                std::fs::write(path.with_extension("frag"), fs_source).unwrap();
+            }
+
             // Attach shaders
             self.gl.attach_shader(program.id, vs_id);
             self.gl.attach_shader(program.id, fs_id);
 
             // Bind vertex attributes
             for (i, attr) in descriptor
                 .vertex_attributes
                 .iter()
--- a/gfx/wr/webrender/src/renderer.rs
+++ b/gfx/wr/webrender/src/renderer.rs
@@ -2020,16 +2020,17 @@ impl Renderer {
         let debug_server = new_debug_server(options.start_debug_server, api_tx.clone());
 
         let mut device = Device::new(
             gl,
             options.resource_override_path.clone(),
             options.upload_method.clone(),
             options.cached_programs.take(),
             options.allow_pixel_local_storage_support,
+            options.dump_shader_source.take(),
         );
 
         let supports_dual_source_blending = match gl_type {
             gl::GlType::Gl => device.supports_extension("GL_ARB_blend_func_extended") &&
                 device.supports_extension("GL_ARB_explicit_attrib_location"),
             gl::GlType::Gles => device.supports_extension("GL_EXT_blend_func_extended"),
         };
         let use_dual_source_blending =
@@ -5684,16 +5685,18 @@ pub struct RendererOptions {
     /// and not complete. This option will probably be removed once support is
     /// complete, and WR can implicitly choose whether to make use of PLS.
     pub allow_pixel_local_storage_support: bool,
     /// Number of batches to look back in history for adding the current
     /// transparent instance into.
     pub batch_lookback_count: usize,
     /// Start the debug server for this renderer.
     pub start_debug_server: bool,
+    /// Output the source of the shader with the given name.
+    pub dump_shader_source: Option<String>,
 }
 
 impl Default for RendererOptions {
     fn default() -> Self {
         RendererOptions {
             device_pixel_ratio: 1.0,
             resource_override_path: None,
             enable_aa: true,
@@ -5731,16 +5734,17 @@ impl Default for RendererOptions {
             allow_advanced_blend_equation: false,
             allow_pixel_local_storage_support: false,
             batch_lookback_count: DEFAULT_BATCH_LOOKBACK_COUNT,
             // For backwards compatibility we set this to true by default, so
             // that if the debugger feature is enabled, the debug server will
             // be started automatically. Users can explicitly disable this as
             // needed.
             start_debug_server: true,
+            dump_shader_source: None,
         }
     }
 }
 
 pub trait DebugServer {
     fn send(&mut self, _message: String);
 }
 
@@ -6242,9 +6246,8 @@ fn get_vao<'a>(vertex_array_kind: Vertex
     }
 }
 
 #[derive(Clone, Copy, PartialEq)]
 enum FramebufferKind {
     Main,
     Other,
 }
-
--- a/gfx/wr/wrench/src/args.yaml
+++ b/gfx/wr/wrench/src/args.yaml
@@ -66,16 +66,21 @@ args:
       help: Disable scissors when clearing render targets
   - no_batch:
       long: no-batch
       help: Disable batching of instanced draw calls
   - chase:
       long: chase
       help: Chase a particular primitive matching the local rect
       takes_value: true
+  - dump_shader_source:
+      long: dump-shader-source
+      help: Dump the source of the specified shader
+      takes_value: true
+      global: true
 
 subcommands:
     - png:
         about: render frame described by YAML and save it to a png file
         args:
           - surface:
               short: s
               long: surface
--- a/gfx/wr/wrench/src/main.rs
+++ b/gfx/wr/wrench/src/main.rs
@@ -460,16 +460,18 @@ fn main() {
                 LayoutPoint::new(items[0], items[1]),
                 LayoutSize::new(items[2], items[3]),
             );
             webrender::ChasePrimitive::LocalRect(rect)
         },
         None => webrender::ChasePrimitive::Nothing,
     };
 
+    let dump_shader_source = args.value_of("dump_shader_source").map(String::from);
+
     let mut events_loop = if args.is_present("headless") {
         None
     } else {
         Some(winit::EventsLoop::new())
     };
 
     let mut window = make_window(
         size, dp_ratio, args.is_present("vsync"), &events_loop, args.is_present("angle"),
@@ -498,16 +500,17 @@ fn main() {
         args.is_present("no_subpixel_aa"),
         args.is_present("verbose"),
         args.is_present("no_scissor"),
         args.is_present("no_batch"),
         args.is_present("precache"),
         args.is_present("slow_subpixel"),
         zoom_factor.unwrap_or(1.0),
         chase_primitive,
+        dump_shader_source,
         notifier,
     );
 
     if let Some(window_title) = wrench.take_title() {
         if !cfg!(windows) {
             window.set_title(&window_title);
         }
     }
--- a/gfx/wr/wrench/src/wrench.rs
+++ b/gfx/wr/wrench/src/wrench.rs
@@ -176,16 +176,17 @@ impl Wrench {
         no_subpixel_aa: bool,
         verbose: bool,
         no_scissor: bool,
         no_batch: bool,
         precache_shaders: bool,
         disable_dual_source_blending: bool,
         zoom_factor: f32,
         chase_primitive: webrender::ChasePrimitive,
+        dump_shader_source: Option<String>,
         notifier: Option<Box<RenderNotifier>>,
     ) -> Self {
         println!("Shader override path: {:?}", shader_override_path);
 
         let recorder = save_type.map(|save_type| match save_type {
             SaveType::Yaml => Box::new(
                 YamlFrameWriterReceiver::new(&PathBuf::from("yaml_frames")),
             ) as Box<webrender::ApiRecordingReceiver>,
@@ -219,16 +220,17 @@ impl Wrench {
             precache_flags,
             blob_image_handler: Some(Box::new(blob::CheckerboardRenderer::new(callbacks.clone()))),
             chase_primitive,
             enable_picture_caching: true,
             testing: true,
             max_texture_size: Some(8196), // Needed for rawtest::test_resize_image.
             allow_dual_source_blending: !disable_dual_source_blending,
             allow_advanced_blend_equation: true,
+            dump_shader_source,
             ..Default::default()
         };
 
         // put an Awakened event into the queue to kick off the first frame
         if let Some(ref _elp) = proxy {
             #[cfg(not(target_os = "android"))]
             let _ = _elp.wakeup();
         }