Bug 1594128 - Encode the brush shader type in the instance attributes. r=gw
authorNicolas Silva <nsilva@mozilla.com>
Wed, 27 Nov 2019 13:22:48 +0000
changeset 504202 9e1443b6c17c81bc5b074b4d33600a3717c55d8e
parent 504201 a1138b7e56a3be562fe49e5b1dc755ed34ebf389
child 504203 e55fa1d9bb896507057a99a33bf281598d2b287d
push id101806
push usernsilva@mozilla.com
push dateThu, 28 Nov 2019 09:30:22 +0000
treeherderautoland@1bcbb2e808a7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgw
bugs1594128
milestone72.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 1594128 - Encode the brush shader type in the instance attributes. r=gw This will allow the upcoming super-brush shader to select its behavior at runtime. Differential Revision: https://phabricator.services.mozilla.com/D53724
gfx/wr/webrender/res/brush.glsl
gfx/wr/webrender/res/prim_shared.glsl
gfx/wr/webrender/res/ps_text_run.glsl
gfx/wr/webrender/src/batch.rs
gfx/wr/webrender/src/gpu_types.rs
--- a/gfx/wr/webrender/res/brush.glsl
+++ b/gfx/wr/webrender/res/brush.glsl
@@ -67,16 +67,21 @@ void brush_vs(
 #define BRUSH_FLAG_PERSPECTIVE_INTERPOLATION    1
 #define BRUSH_FLAG_SEGMENT_RELATIVE             2
 #define BRUSH_FLAG_SEGMENT_REPEAT_X             4
 #define BRUSH_FLAG_SEGMENT_REPEAT_Y             8
 #define BRUSH_FLAG_TEXEL_RECT                  16
 
 #define INVALID_SEGMENT_INDEX                   0xffff
 
+// These constants must match the BrushShaderKind enum in gpu_types.rs.
+#define BRUSH_KIND_SOLID 0x1000000
+#define BRUSH_KIND_IMAGE 0x2000000
+#define BRUSH_KIND_TEXT  0x4000000
+
 void main(void) {
     // Load the brush instance from vertex attributes.
     Instance instance = decode_instance_attributes();
     int edge_flags = (instance.flags >> 16) & 0xff;
     int brush_flags = (instance.flags >> 24) & 0xff;
     PrimitiveHeader ph = fetch_prim_header(instance.prim_header_address);
 
     // Fetch the segment of this brush primitive we are drawing.
@@ -153,17 +158,17 @@ void main(void) {
 
     // Run the specific brush VS code to write interpolators.
     brush_vs(
         vi,
         ph.specific_prim_address,
         ph.local_rect,
         segment_rect,
         ph.user_data,
-        instance.user_data,
+        instance.resource_address,
         transform.m,
         pic_task,
         brush_flags,
         segment_data
     );
 }
 #endif
 
--- a/gfx/wr/webrender/res/prim_shared.glsl
+++ b/gfx/wr/webrender/res/prim_shared.glsl
@@ -52,28 +52,30 @@ in ivec4 aData;
 
 struct Instance
 {
     int prim_header_address;
     int picture_task_address;
     int clip_address;
     int segment_index;
     int flags;
-    int user_data;
+    int resource_address;
+    int brush_kind;
 };
 
 Instance decode_instance_attributes() {
     Instance instance;
 
     instance.prim_header_address = aData.x;
     instance.picture_task_address = aData.y >> 16;
     instance.clip_address = aData.y & 0xffff;
     instance.segment_index = aData.z & 0xffff;
     instance.flags = aData.z & 0xffff0000;
-    instance.user_data = aData.w;
+    instance.resource_address = aData.w & 0xffffff;
+    instance.brush_kind = aData.w & 0xff000000;
 
     return instance;
 }
 
 struct PrimitiveHeader {
     RectWithSize local_rect;
     RectWithSize local_clip_rect;
     float z;
--- a/gfx/wr/webrender/res/ps_text_run.glsl
+++ b/gfx/wr/webrender/res/ps_text_run.glsl
@@ -173,34 +173,33 @@ VertexInfo write_text_vertex(RectWithSiz
 }
 
 void main(void) {
     Instance instance = decode_instance_attributes();
 
     int glyph_index = instance.segment_index;
     int subpx_dir = (instance.flags >> 24) & 0xff;
     int color_mode = (instance.flags >> 16) & 0xff;
-    int resource_address = instance.user_data;
 
     PrimitiveHeader ph = fetch_prim_header(instance.prim_header_address);
     Transform transform = fetch_transform(ph.transform_id);
     ClipArea clip_area = fetch_clip_area(instance.clip_address);
     PictureTask task = fetch_picture_task(instance.picture_task_address);
 
     TextRun text = fetch_text_run(ph.specific_prim_address);
     vec2 text_offset = vec2(ph.user_data.xy) / 256.0;
 
     if (color_mode == COLOR_MODE_FROM_PASS) {
         color_mode = uMode;
     }
 
     Glyph glyph = fetch_glyph(ph.specific_prim_address, glyph_index);
     glyph.offset += ph.local_rect.p0 - text_offset;
 
-    GlyphResource res = fetch_glyph_resource(resource_address);
+    GlyphResource res = fetch_glyph_resource(instance.resource_address);
 
 #ifdef WR_FEATURE_GLYPH_TRANSFORM
     // Transform from local space to glyph space.
     mat2 glyph_transform = mat2(transform.m) * task.device_pixel_scale;
 
     // Compute the glyph rect in glyph space.
     RectWithSize glyph_rect = RectWithSize(res.offset + glyph_transform * (text_offset + glyph.offset),
                                            res.uv_rect.zw - res.uv_rect.xy);
--- a/gfx/wr/webrender/src/batch.rs
+++ b/gfx/wr/webrender/src/batch.rs
@@ -6,17 +6,17 @@ use api::{AlphaType, ClipMode, ExternalI
 use api::{YuvColorSpace, YuvFormat, ColorDepth, ColorRange, PremultipliedColorF};
 use api::units::*;
 use crate::clip::{ClipDataStore, ClipNodeFlags, ClipNodeRange, ClipItemKind, ClipStore};
 use crate::clip_scroll_tree::{ClipScrollTree, ROOT_SPATIAL_NODE_INDEX, SpatialNodeIndex, CoordinateSystemId};
 use crate::composite::{CompositeState, CompositeTile, CompositeTileSurface};
 use crate::glyph_rasterizer::GlyphFormat;
 use crate::gpu_cache::{GpuBlockData, GpuCache, GpuCacheHandle, GpuCacheAddress};
 use crate::gpu_types::{BrushFlags, BrushInstance, PrimitiveHeaders, ZBufferId, ZBufferIdGenerator};
-use crate::gpu_types::{ClipMaskInstance, SplitCompositeInstance};
+use crate::gpu_types::{ClipMaskInstance, SplitCompositeInstance, BrushShaderKind};
 use crate::gpu_types::{PrimitiveInstanceData, RasterizationSpace, GlyphInstance};
 use crate::gpu_types::{PrimitiveHeader, PrimitiveHeaderIndex, TransformPaletteId, TransformPalette};
 use crate::internal_types::{FastHashMap, SavedTargetIndex, Swizzle, TextureSource, Filter};
 use crate::picture::{Picture3DContext, PictureCompositeMode, PicturePrimitive, TileSurface};
 use crate::prim_store::{DeferredResolve, EdgeAaSegmentMask, PrimitiveInstanceKind, PrimitiveVisibilityIndex, PrimitiveVisibilityMask};
 use crate::prim_store::{VisibleGradientTile, PrimitiveInstance, PrimitiveOpacity, SegmentInstanceIndex};
 use crate::prim_store::{BrushSegment, ClipMaskKind, ClipTaskIndex, VECS_PER_SEGMENT, SpaceMapper};
 use crate::prim_store::image::ImageSource;
@@ -65,16 +65,27 @@ pub enum BrushBatchKind {
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub enum BatchKind {
     SplitComposite,
     TextRun(GlyphFormat),
     Brush(BrushBatchKind),
 }
 
+impl BatchKind {
+    fn shader_kind(&self) -> BrushShaderKind {
+        match self {
+            BatchKind::Brush(BrushBatchKind::Solid) => BrushShaderKind::Solid,
+            BatchKind::Brush(BrushBatchKind::Image(..)) => BrushShaderKind::Image,
+            BatchKind::TextRun(..) => BrushShaderKind::Text,
+            _ => BrushShaderKind::None,
+        }
+    }
+}
+
 /// Optional textures that can be used as a source in the shaders.
 /// Textures that are not used by the batch are equal to TextureId::invalid().
 #[derive(Copy, Clone, Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct BatchTextures {
     pub colors: [TextureSource; 3],
 }
@@ -570,31 +581,32 @@ impl BatchBuilder {
         features: BatchFeatures,
         bounding_rect: &PictureRect,
         z_id: ZBufferId,
         segment_index: i32,
         edge_flags: EdgeAaSegmentMask,
         clip_task_address: RenderTaskAddress,
         brush_flags: BrushFlags,
         prim_header_index: PrimitiveHeaderIndex,
-        user_data: i32,
+        resource_address: i32,
         prim_vis_mask: PrimitiveVisibilityMask,
     ) {
         for batcher in &mut self.batchers {
             if batcher.vis_mask.intersects(prim_vis_mask) {
                 let render_task_address = batcher.render_task_address;
 
                 let instance = BrushInstance {
                     segment_index,
                     edge_flags,
                     clip_task_address,
                     render_task_address,
                     brush_flags,
                     prim_header_index,
-                    user_data,
+                    resource_address,
+                    brush_kind: batch_key.kind.shader_kind(),
                 };
 
                 batcher.push_single_instance(
                     batch_key,
                     features,
                     bounding_rect,
                     z_id,
                     PrimitiveInstanceData::from(instance),
--- a/gfx/wr/webrender/src/gpu_types.rs
+++ b/gfx/wr/webrender/src/gpu_types.rs
@@ -58,16 +58,31 @@ impl ZBufferIdGenerator {
     pub fn next(&mut self) -> ZBufferId {
         debug_assert!(self.next < MAX_ITEMS_PER_DOCUMENT_LAYER);
         let id = ZBufferId(self.next + self.base);
         self.next += 1;
         id
     }
 }
 
+/// A shader kind identifier that can be used by a generic-shader to select the behavior at runtime.
+///
+/// Not all brush kinds need to be present in this enum, only those we want to support in the generic
+/// brush shader.
+/// Do not use the 24 lowest bits. This will be packed with other information in the vertex attributes.
+/// The constants must match the corresponding defines in brush.glsl.
+#[repr(i32)]
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub enum BrushShaderKind {
+    None = 0,
+    Solid = 0x1000000,
+    Image = 0x2000000,
+    Text = 0x4000000,
+}
+
 #[derive(Debug, Copy, Clone)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 #[repr(C)]
 pub enum RasterizationSpace {
     Local = 0,
     Screen = 1,
 }
@@ -337,23 +352,23 @@ impl GlyphInstance {
         GlyphInstance {
             prim_header_index,
         }
     }
 
     // TODO(gw): Some of these fields can be moved to the primitive
     //           header since they are constant, and some can be
     //           compressed to a smaller size.
-    pub fn build(&self, data0: i32, data1: i32, data2: i32) -> PrimitiveInstanceData {
+    pub fn build(&self, data0: i32, data1: i32, resource_address: i32) -> PrimitiveInstanceData {
         PrimitiveInstanceData {
             data: [
                 self.prim_header_index.0 as i32,
                 data0,
                 data1,
-                data2,
+                resource_address | BrushShaderKind::Text as i32,
             ],
         }
     }
 }
 
 pub struct SplitCompositeInstance {
     pub prim_header_index: PrimitiveHeaderIndex,
     pub polygons_address: GpuCacheAddress,
@@ -390,41 +405,40 @@ bitflags! {
         const SEGMENT_REPEAT_X = 0x4;
         /// Repeat UVs vertically.
         const SEGMENT_REPEAT_Y = 0x8;
         /// The extra segment data is a texel rect.
         const SEGMENT_TEXEL_RECT = 0x10;
     }
 }
 
-// TODO(gw): Some of these fields can be moved to the primitive
-//           header since they are constant, and some can be
-//           compressed to a smaller size.
-#[repr(C)]
+/// Convenience structure to encode into PrimitiveInstanceData.
 pub struct BrushInstance {
     pub prim_header_index: PrimitiveHeaderIndex,
     pub render_task_address: RenderTaskAddress,
     pub clip_task_address: RenderTaskAddress,
     pub segment_index: i32,
     pub edge_flags: EdgeAaSegmentMask,
     pub brush_flags: BrushFlags,
-    pub user_data: i32,
+    pub resource_address: i32,
+    pub brush_kind: BrushShaderKind,
 }
 
 impl From<BrushInstance> for PrimitiveInstanceData {
     fn from(instance: BrushInstance) -> Self {
         PrimitiveInstanceData {
             data: [
                 instance.prim_header_index.0,
-                ((instance.render_task_address.0 as i32) << 16) |
-                instance.clip_task_address.0 as i32,
-                instance.segment_index |
-                ((instance.edge_flags.bits() as i32) << 16) |
-                ((instance.brush_flags.bits() as i32) << 24),
-                instance.user_data,
+                ((instance.render_task_address.0 as i32) << 16)
+                | instance.clip_task_address.0 as i32,
+                instance.segment_index
+                | ((instance.edge_flags.bits() as i32) << 16)
+                | ((instance.brush_flags.bits() as i32) << 24),
+                instance.resource_address
+                | instance.brush_kind as i32,
             ]
         }
     }
 }
 
 // Represents the information about a transform palette
 // entry that is passed to shaders. It includes an index
 // into the transform palette, and a set of flags. The