Bug 1594128 - Encode the brush shader type in the instance attributes. r=gw
authorNicolas Silva <nsilva@mozilla.com>
Thu, 21 Nov 2019 17:36:53 +0000
changeset 503312 74554530a51089d0145a91587ab1e6d4e8c762f2
parent 503311 e894fff26e422166618de4401464929e9b9cb62e
child 503313 912718966a67fb7cf2f21c2690dce0bd5822377a
push id36833
push userbtara@mozilla.com
push dateFri, 22 Nov 2019 21:40:53 +0000
treeherdermozilla-central@2c912e46295e [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