Skip to content

Commit

Permalink
Use all four channels in the mask texture.
Browse files Browse the repository at this point in the history
Each bundle of four pixels on a scanline is packed into the RGBA channels of
the mask texture. The area LUT is also expanded to be RGBA so that four pixels'
worth of areas can be looked up at once.

Nice improvement on `paris-30k` from MPVG.

Closes rust-windowing#262.
  • Loading branch information
pcwalton committed May 5, 2020
1 parent c7ce215 commit 478008d
Show file tree
Hide file tree
Showing 25 changed files with 276 additions and 201 deletions.
33 changes: 24 additions & 9 deletions demo/common/src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::{BackgroundColor, Options};
use pathfinder_color::ColorU;
use pathfinder_geometry::rect::RectI;
use pathfinder_geometry::vector::{Vector2I, vec2i};
use pathfinder_gpu::Device;
use pathfinder_gpu::{Device, TextureFormat};
use pathfinder_renderer::gpu::debug::DebugUIPresenter;
use pathfinder_resources::ResourceLoader;
use pathfinder_ui::{BUTTON_HEIGHT, BUTTON_TEXT_OFFSET, BUTTON_WIDTH, FONT_ASCENT, PADDING};
Expand Down Expand Up @@ -121,15 +121,30 @@ where
D: Device,
{
pub fn new(device: &D, resources: &dyn ResourceLoader) -> DemoUIPresenter<D> {
let effects_texture = device.create_texture_from_png(resources, EFFECTS_PNG_NAME);
let open_texture = device.create_texture_from_png(resources, OPEN_PNG_NAME);
let rotate_texture = device.create_texture_from_png(resources, ROTATE_PNG_NAME);
let zoom_in_texture = device.create_texture_from_png(resources, ZOOM_IN_PNG_NAME);
let effects_texture = device.create_texture_from_png(resources,
EFFECTS_PNG_NAME,
TextureFormat::R8);
let open_texture = device.create_texture_from_png(resources,
OPEN_PNG_NAME,
TextureFormat::R8);
let rotate_texture = device.create_texture_from_png(resources,
ROTATE_PNG_NAME,
TextureFormat::R8);
let zoom_in_texture = device.create_texture_from_png(resources,
ZOOM_IN_PNG_NAME,
TextureFormat::R8);
let zoom_actual_size_texture = device.create_texture_from_png(resources,
ZOOM_ACTUAL_SIZE_PNG_NAME);
let zoom_out_texture = device.create_texture_from_png(resources, ZOOM_OUT_PNG_NAME);
let background_texture = device.create_texture_from_png(resources, BACKGROUND_PNG_NAME);
let screenshot_texture = device.create_texture_from_png(resources, SCREENSHOT_PNG_NAME);
ZOOM_ACTUAL_SIZE_PNG_NAME,
TextureFormat::R8);
let zoom_out_texture = device.create_texture_from_png(resources,
ZOOM_OUT_PNG_NAME,
TextureFormat::R8);
let background_texture = device.create_texture_from_png(resources,
BACKGROUND_PNG_NAME,
TextureFormat::R8);
let screenshot_texture = device.create_texture_from_png(resources,
SCREENSHOT_PNG_NAME,
TextureFormat::R8);

DemoUIPresenter {
effects_texture,
Expand Down
25 changes: 19 additions & 6 deletions gpu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,26 @@ pub trait Device: Sized {
fn try_recv_texture_data(&self, receiver: &Self::TextureDataReceiver) -> Option<TextureData>;
fn recv_texture_data(&self, receiver: &Self::TextureDataReceiver) -> TextureData;

fn create_texture_from_png(&self, resources: &dyn ResourceLoader, name: &str) -> Self::Texture {
fn create_texture_from_png(&self,
resources: &dyn ResourceLoader,
name: &str,
format: TextureFormat)
-> Self::Texture {
let data = resources.slurp(&format!("textures/{}.png", name)).unwrap();
let image = image::load_from_memory_with_format(&data, ImageFormat::Png)
.unwrap()
.to_luma();
let size = vec2i(image.width() as i32, image.height() as i32);
self.create_texture_from_data(TextureFormat::R8, size, TextureDataRef::U8(&image))
let image = image::load_from_memory_with_format(&data, ImageFormat::Png).unwrap();
match format {
TextureFormat::R8 => {
let image = image.to_luma();
let size = vec2i(image.width() as i32, image.height() as i32);
self.create_texture_from_data(format, size, TextureDataRef::U8(&image))
}
TextureFormat::RGBA8 => {
let image = image.to_rgba();
let size = vec2i(image.width() as i32, image.height() as i32);
self.create_texture_from_data(format, size, TextureDataRef::U8(&image))
}
_ => unimplemented!(),
}
}

fn create_program_from_shader_names(
Expand Down
25 changes: 15 additions & 10 deletions renderer/src/gpu/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ const TEXTURE_METADATA_TEXTURE_WIDTH: i32 = TEXTURE_METADATA_ENTRIES_PER_ROW *
const TEXTURE_METADATA_TEXTURE_HEIGHT: i32 = 65536 / TEXTURE_METADATA_ENTRIES_PER_ROW;

// FIXME(pcwalton): Shrink this again!
const MASK_FRAMEBUFFER_WIDTH: i32 = TILE_WIDTH as i32 * MASK_TILES_ACROSS as i32;
const MASK_FRAMEBUFFER_HEIGHT: i32 = TILE_HEIGHT as i32 * MASK_TILES_DOWN as i32;
const MASK_FRAMEBUFFER_WIDTH: i32 = TILE_WIDTH as i32 * MASK_TILES_ACROSS as i32;
const MASK_FRAMEBUFFER_HEIGHT: i32 = TILE_HEIGHT as i32 / 4 * MASK_TILES_DOWN as i32;

const COMBINER_CTRL_COLOR_COMBINE_SRC_IN: i32 = 0x1;
const COMBINER_CTRL_COLOR_COMBINE_DEST_IN: i32 = 0x2;
Expand Down Expand Up @@ -170,8 +170,10 @@ impl<D> Renderer<D> where D: Device {
let stencil_program = StencilProgram::new(&device, resources);
let reprojection_program = ReprojectionProgram::new(&device, resources);

let area_lut_texture = device.create_texture_from_png(resources, "area-lut");
let gamma_lut_texture = device.create_texture_from_png(resources, "gamma-lut");
let area_lut_texture =
device.create_texture_from_png(resources, "area-lut", TextureFormat::RGBA8);
let gamma_lut_texture =
device.create_texture_from_png(resources, "gamma-lut", TextureFormat::R8);

let quad_vertex_positions_buffer = device.create_buffer(BufferUploadMode::Static);
device.allocate_buffer(&quad_vertex_positions_buffer,
Expand Down Expand Up @@ -906,7 +908,10 @@ impl<D> Renderer<D> where D: Device {

if let Some(alpha_tile_page) = self.back_frame.alpha_tile_pages.get(&tile_page) {
uniforms.push((&self.tile_program.mask_texture_0_uniform,
UniformData::TextureUnit(textures.len() as u32)));
UniformData::TextureUnit(textures.len() as u32)));
uniforms.push((&self.tile_program.mask_texture_size_0_uniform,
UniformData::Vec2(F32x2::new(MASK_FRAMEBUFFER_WIDTH as f32,
MASK_FRAMEBUFFER_HEIGHT as f32))));
textures.push(self.device.framebuffer_texture(&alpha_tile_page.framebuffer));
}

Expand All @@ -919,16 +924,16 @@ impl<D> Renderer<D> where D: Device {
self.device.set_texture_sampling_mode(color_texture_page,
color_texture.sampling_flags);
uniforms.push((&self.tile_program.color_texture_0_uniform,
UniformData::TextureUnit(textures.len() as u32)));
uniforms.push((&self.tile_program.color_texture_0_size_uniform,
UniformData::Vec2(color_texture_size.0)));
UniformData::TextureUnit(textures.len() as u32)));
uniforms.push((&self.tile_program.color_texture_size_0_uniform,
UniformData::Vec2(color_texture_size.0)));
textures.push(color_texture_page);

ctrl |= color_texture.composite_op.to_combine_mode() <<
COMBINER_CTRL_COLOR_COMBINE_SHIFT;
}
None => {
uniforms.push((&self.tile_program.color_texture_0_size_uniform,
uniforms.push((&self.tile_program.color_texture_size_0_uniform,
UniformData::Vec2(F32x2::default())));
}
}
Expand Down Expand Up @@ -1913,7 +1918,7 @@ struct AlphaTilePage<D> where D: Device {
impl<D> AlphaTilePage<D> where D: Device {
fn new(device: &mut D) -> AlphaTilePage<D> {
let framebuffer_size = vec2i(MASK_FRAMEBUFFER_WIDTH, MASK_FRAMEBUFFER_HEIGHT);
let framebuffer_texture = device.create_texture(TextureFormat::R16F, framebuffer_size);
let framebuffer_texture = device.create_texture(TextureFormat::RGBA16F, framebuffer_size);
let framebuffer = device.create_framebuffer(framebuffer_texture);
AlphaTilePage {
buffered_fills: vec![],
Expand Down
11 changes: 7 additions & 4 deletions renderer/src/gpu/shaders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ pub struct FillComputeProgram<D> where D: Device {
impl<D> FillComputeProgram<D> where D: Device {
pub fn new(device: &D, resources: &dyn ResourceLoader) -> FillComputeProgram<D> {
let mut program = device.create_compute_program(resources, "fill");
let local_size = ComputeDimensions { x: TILE_WIDTH, y: TILE_HEIGHT, z: 1 };
let local_size = ComputeDimensions { x: TILE_WIDTH, y: TILE_HEIGHT / 4, z: 1 };
device.set_compute_program_local_size(&mut program, local_size);

let dest_uniform = device.get_uniform(&program, "Dest");
Expand Down Expand Up @@ -418,10 +418,11 @@ pub struct TileProgram<D> where D: Device {
pub texture_metadata_size_uniform: D::Uniform,
pub dest_texture_uniform: D::Uniform,
pub color_texture_0_uniform: D::Uniform,
pub color_texture_size_0_uniform: D::Uniform,
pub color_texture_1_uniform: D::Uniform,
pub mask_texture_0_uniform: D::Uniform,
pub mask_texture_size_0_uniform: D::Uniform,
pub gamma_lut_uniform: D::Uniform,
pub color_texture_0_size_uniform: D::Uniform,
pub filter_params_0_uniform: D::Uniform,
pub filter_params_1_uniform: D::Uniform,
pub filter_params_2_uniform: D::Uniform,
Expand All @@ -438,10 +439,11 @@ impl<D> TileProgram<D> where D: Device {
let texture_metadata_size_uniform = device.get_uniform(&program, "TextureMetadataSize");
let dest_texture_uniform = device.get_uniform(&program, "DestTexture");
let color_texture_0_uniform = device.get_uniform(&program, "ColorTexture0");
let color_texture_size_0_uniform = device.get_uniform(&program, "ColorTextureSize0");
let color_texture_1_uniform = device.get_uniform(&program, "ColorTexture1");
let mask_texture_0_uniform = device.get_uniform(&program, "MaskTexture0");
let mask_texture_size_0_uniform = device.get_uniform(&program, "MaskTextureSize0");
let gamma_lut_uniform = device.get_uniform(&program, "GammaLUT");
let color_texture_0_size_uniform = device.get_uniform(&program, "ColorTexture0Size");
let filter_params_0_uniform = device.get_uniform(&program, "FilterParams0");
let filter_params_1_uniform = device.get_uniform(&program, "FilterParams1");
let filter_params_2_uniform = device.get_uniform(&program, "FilterParams2");
Expand All @@ -455,10 +457,11 @@ impl<D> TileProgram<D> where D: Device {
texture_metadata_size_uniform,
dest_texture_uniform,
color_texture_0_uniform,
color_texture_size_0_uniform,
color_texture_1_uniform,
mask_texture_0_uniform,
mask_texture_size_0_uniform,
gamma_lut_uniform,
color_texture_0_size_uniform,
filter_params_0_uniform,
filter_params_1_uniform,
filter_params_2_uniform,
Expand Down
6 changes: 3 additions & 3 deletions resources/shaders/gl3/fill.fs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ precision highp sampler2D;



float computeCoverage(vec2 from, vec2 to, sampler2D areaLUT){
vec4 computeCoverage(vec2 from, vec2 to, sampler2D areaLUT){

vec2 left = from . x < to . x ? from : to, right = from . x < to . x ? to : from;

Expand All @@ -43,7 +43,7 @@ float computeCoverage(vec2 from, vec2 to, sampler2D areaLUT){


float dX = window . x - window . y;
return texture(areaLUT, vec2(y + 8.0, abs(d * dX))/ 16.0). r * dX;
return texture(areaLUT, vec2(y + 8.0, abs(d * dX))/ 16.0)* dX;
}


Expand All @@ -55,6 +55,6 @@ in vec2 vTo;
out vec4 oFragColor;

void main(){
oFragColor = vec4(computeCoverage(vFrom, vTo, uAreaLUT));
oFragColor = computeCoverage(vFrom, vTo, uAreaLUT);
}

12 changes: 9 additions & 3 deletions resources/shaders/gl3/fill.vs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ out vec2 vTo;
vec2 computeTileOffset(uint tileIndex, float stencilTextureWidth){
uint tilesPerRow = uint(stencilTextureWidth / uTileSize . x);
uvec2 tileOffset = uvec2(tileIndex % tilesPerRow, tileIndex / tilesPerRow);
return vec2(tileOffset)* uTileSize;
return vec2(tileOffset)* uTileSize * vec2(1.0, 0.25);
}

void main(){
Expand All @@ -49,9 +49,15 @@ void main(){
position . y = floor(min(from . y, to . y));
else
position . y = uTileSize . y;
position . y = floor(position . y * 0.25);

vFrom = from - position;
vTo = to - position;




vec2 offset = vec2(0.0, 1.5)- position * vec2(1.0, 4.0);
vFrom = from + offset;
vTo = to + offset;

vec2 globalPosition =(tileOrigin + position)/ uFramebufferSize * 2.0 - 1.0;

Expand Down
14 changes: 10 additions & 4 deletions resources/shaders/gl3/tile.fs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,12 @@ uniform sampler2D uColorTexture0;
uniform sampler2D uMaskTexture0;
uniform sampler2D uDestTexture;
uniform sampler2D uGammaLUT;
uniform vec2 uColorTextureSize0;
uniform vec2 uMaskTextureSize0;
uniform vec4 uFilterParams0;
uniform vec4 uFilterParams1;
uniform vec4 uFilterParams2;
uniform vec2 uFramebufferSize;
uniform vec2 uColorTexture0Size;
uniform int uCtrl;

in vec3 vMaskTexCoord0;
Expand Down Expand Up @@ -544,11 +545,16 @@ vec4 composite(vec4 srcColor,

float sampleMask(float maskAlpha,
sampler2D maskTexture,
vec2 maskTextureSize,
vec3 maskTexCoord,
int maskCtrl){
if(maskCtrl == 0)
return maskAlpha;
float coverage = texture(maskTexture, maskTexCoord . xy). r + maskTexCoord . z;

ivec2 maskTexCoordI = ivec2(floor(maskTexCoord . xy));
vec4 texel = texture(maskTexture,(vec2(maskTexCoordI / ivec2(1, 4))+ 0.5)/ maskTextureSize);
float coverage = texel[maskTexCoordI . y % 4]+ maskTexCoord . z;

if((maskCtrl & 0x1)!= 0)
coverage = abs(coverage);
else
Expand All @@ -562,7 +568,7 @@ void calculateColor(int tileCtrl, int ctrl){

int maskCtrl0 =(tileCtrl >> 0)& 0x3;
float maskAlpha = 1.0;
maskAlpha = sampleMask(maskAlpha, uMaskTexture0, vMaskTexCoord0, maskCtrl0);
maskAlpha = sampleMask(maskAlpha, uMaskTexture0, uMaskTextureSize0, vMaskTexCoord0, maskCtrl0);


vec4 color = vBaseColor;
Expand All @@ -573,7 +579,7 @@ void calculateColor(int tileCtrl, int ctrl){
vec4 color0 = filterColor(vColorTexCoord0,
uColorTexture0,
uGammaLUT,
uColorTexture0Size,
uColorTextureSize0,
gl_FragCoord . xy,
uFramebufferSize,
uFilterParams0,
Expand Down
2 changes: 1 addition & 1 deletion resources/shaders/gl3/tile.vs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ void main(){
vec2 tileOrigin = vec2(aTileOrigin), tileOffset = vec2(aTileOffset);
vec2 position =(tileOrigin + tileOffset)* uTileSize;

vec2 maskTexCoord0 =(vec2(aMaskTexCoord0)+ tileOffset)/ 256.0;
vec2 maskTexCoord0 =(vec2(aMaskTexCoord0)+ tileOffset)* uTileSize;

vec2 textureMetadataScale = vec2(1.0)/ vec2(uTextureMetadataSize);
vec2 metadataEntryCoord = vec2(aColor % 128 * 4, aColor / 128);
Expand Down
3 changes: 1 addition & 2 deletions resources/shaders/gl3/tile_clip.fs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ in float vBackdrop;
out vec4 oFragColor;

void main(){
float alpha = clamp(abs(texture(uSrc, vTexCoord). r + vBackdrop), 0.0, 1.0);
oFragColor = vec4(alpha, 0.0, 0.0, 1.0);
oFragColor = clamp(abs(texture(uSrc, vTexCoord)+ vBackdrop), 0.0, 1.0);
}

32 changes: 15 additions & 17 deletions resources/shaders/metal/fill.cs.metal
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ struct bNextFills
int iNextFills[1];
};

constant uint3 gl_WorkGroupSize [[maybe_unused]] = uint3(16u, 16u, 1u);
constant uint3 gl_WorkGroupSize [[maybe_unused]] = uint3(16u, 4u, 1u);

static inline __attribute__((always_inline))
float computeCoverage(thread const float2& from, thread const float2& to, thread const texture2d<float> areaLUT, thread const sampler areaLUTSmplr)
float4 computeCoverage(thread const float2& from, thread const float2& to, thread const texture2d<float> areaLUT, thread const sampler areaLUTSmplr)
{
float2 left = select(to, from, bool2(from.x < to.x));
float2 right = select(from, to, bool2(from.x < to.x));
Expand All @@ -34,34 +34,32 @@ float computeCoverage(thread const float2& from, thread const float2& to, thread
float y = mix(left.y, right.y, t);
float d = (right.y - left.y) / (right.x - left.x);
float dX = window.x - window.y;
return areaLUT.sample(areaLUTSmplr, (float2(y + 8.0, abs(d * dX)) / float2(16.0)), level(0.0)).x * dX;
return areaLUT.sample(areaLUTSmplr, (float2(y + 8.0, abs(d * dX)) / float2(16.0)), level(0.0)) * dX;
}

kernel void main0(constant int& uFirstTileIndex [[buffer(0)]], const device bFillTileMap& _165 [[buffer(1)]], const device bFills& _186 [[buffer(2)]], const device bNextFills& _269 [[buffer(3)]], texture2d<float> uAreaLUT [[texture(0)]], texture2d<float, access::write> uDest [[texture(1)]], sampler uAreaLUTSmplr [[sampler(0)]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]])
kernel void main0(constant int& uFirstTileIndex [[buffer(0)]], const device bFillTileMap& _150 [[buffer(1)]], const device bFills& _173 [[buffer(2)]], const device bNextFills& _256 [[buffer(3)]], texture2d<float> uAreaLUT [[texture(0)]], texture2d<float, access::write> uDest [[texture(1)]], sampler uAreaLUTSmplr [[sampler(0)]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]])
{
int2 tileSubCoord = int2(gl_LocalInvocationID.xy);
int2 tileSubCoord = int2(gl_LocalInvocationID.xy) * int2(1, 4);
uint tileIndexOffset = gl_WorkGroupID.z;
uint tileIndex = tileIndexOffset + uint(uFirstTileIndex);
int2 tileOrigin = int2(int(tileIndex & 255u), int((tileIndex >> 8u) & 255u)) * int2(16);
int2 destCoord = tileOrigin + tileSubCoord;
int fillIndex = _165.iFillTileMap[tileIndex];
int fillIndex = _150.iFillTileMap[tileIndex];
if (fillIndex < 0)
{
return;
}
float coverage = 0.0;
float4 coverages = float4(0.0);
do
{
uint2 fill = _186.iFills[fillIndex];
uint2 fill = _173.iFills[fillIndex];
float2 from = float2(float(fill.y & 15u), float((fill.y >> 4u) & 15u)) + (float2(float(fill.x & 255u), float((fill.x >> 8u) & 255u)) / float2(256.0));
float2 to = float2(float((fill.y >> 8u) & 15u), float((fill.y >> 12u) & 15u)) + (float2(float((fill.x >> 16u) & 255u), float((fill.x >> 24u) & 255u)) / float2(256.0));
from -= (float2(tileSubCoord) + float2(0.5));
to -= (float2(tileSubCoord) + float2(0.5));
float2 param = from;
float2 param_1 = to;
coverage += computeCoverage(param, param_1, uAreaLUT, uAreaLUTSmplr);
fillIndex = _269.iNextFills[fillIndex];
float2 param = from - (float2(tileSubCoord) + float2(0.5));
float2 param_1 = to - (float2(tileSubCoord) + float2(0.5));
coverages += computeCoverage(param, param_1, uAreaLUT, uAreaLUTSmplr);
fillIndex = _256.iNextFills[fillIndex];
} while (fillIndex >= 0);
uDest.write(float4(coverage), uint2(destCoord));
int2 tileOrigin = int2(int(tileIndex & 255u), int((tileIndex >> 8u) & 255u)) * int2(16, 4);
int2 destCoord = tileOrigin + int2(gl_LocalInvocationID.xy);
uDest.write(coverages, uint2(destCoord));
}

Loading

0 comments on commit 478008d

Please sign in to comment.